blob: a6bba159ea7fb3c2e9b55910519c3d21b147b826 [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
Dan Willemsen1e704462016-08-21 15:17:17 -070066
67 // From the arguments
MarkDacekd0e7cd32022-12-02 22:22:40 +000068 parallel int
69 keepGoing int
70 verbose bool
71 checkbuild bool
72 dist bool
73 jsonModuleGraph bool
74 apiBp2build bool // Generate BUILD files for Soong modules that contribute APIs
75 bp2build bool
76 queryview bool
77 reportMkMetrics bool // Collect and report mk2bp migration progress metrics.
78 soongDocs bool
79 skipConfig bool
80 skipKati bool
81 skipKatiNinja bool
82 skipSoong bool
83 skipNinja bool
84 skipSoongTests bool
85 searchApiDir bool // Scan the Android.bp files generated in out/api_surfaces
86 skipMetricsUpload bool
Dan Willemsen1e704462016-08-21 15:17:17 -070087
88 // From the product config
Dan Willemsen6ab79db2018-05-02 00:06:28 -070089 katiArgs []string
90 ninjaArgs []string
91 katiSuffix string
92 targetDevice string
93 targetDeviceDir string
Spandan Dasa3639e62021-05-25 19:14:02 +000094 sandboxConfig *SandboxConfig
Dan Willemsen3d60b112018-04-04 22:25:56 -070095
Dan Willemsen2bb82d02019-12-27 09:35:42 -080096 // Autodetected
97 totalRAM uint64
98
Dan Willemsene3336352020-01-02 19:10:38 -080099 brokenDupRules bool
100 brokenUsesNetwork bool
101 brokenNinjaEnvVars []string
Dan Willemsen18490112018-05-25 16:30:04 -0700102
103 pathReplaced bool
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000104
MarkDacekb78465d2022-10-18 20:10:16 +0000105 bazelProdMode bool
106 bazelDevMode bool
107 bazelStagingMode bool
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000108
Colin Crossf3bdbcb2021-06-01 11:43:55 -0700109 // Set by multiproduct_kati
110 emptyNinjaFile bool
Yu Liu6e13b402021-07-27 14:29:06 -0700111
112 metricsUploader string
MarkDacekd06db5d2022-11-29 00:47:59 +0000113
114 bazelForceEnabledModules string
Spandan Dasc5763832022-11-08 18:42:16 +0000115
116 includeTags []string
Dan Willemsen1e704462016-08-21 15:17:17 -0700117}
118
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800119const srcDirFileCheck = "build/soong/root.bp"
120
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700121var buildFiles = []string{"Android.mk", "Android.bp"}
122
Patrice Arruda13848222019-04-22 17:12:02 -0700123type BuildAction uint
124
125const (
126 // Builds all of the modules and their dependencies of a specified directory, relative to the root
127 // directory of the source tree.
128 BUILD_MODULES_IN_A_DIRECTORY BuildAction = iota
129
130 // Builds all of the modules and their dependencies of a list of specified directories. All specified
131 // directories are relative to the root directory of the source tree.
132 BUILD_MODULES_IN_DIRECTORIES
Patrice Arruda39282062019-06-20 16:35:12 -0700133
134 // Build a list of specified modules. If none was specified, simply build the whole source tree.
135 BUILD_MODULES
Patrice Arruda13848222019-04-22 17:12:02 -0700136)
137
138// checkTopDir validates that the current directory is at the root directory of the source tree.
139func checkTopDir(ctx Context) {
140 if _, err := os.Stat(srcDirFileCheck); err != nil {
141 if os.IsNotExist(err) {
142 ctx.Fatalf("Current working directory must be the source tree. %q not found.", srcDirFileCheck)
143 }
144 ctx.Fatalln("Error verifying tree state:", err)
145 }
146}
147
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500148// fetchEnvConfig optionally fetches environment config from an
149// experiments system to control Soong features dynamically.
150func fetchEnvConfig(ctx Context, config *configImpl, envConfigName string) error {
David Goldsmith62243a32022-04-08 13:42:04 +0000151 configName := envConfigName + "." + jsonSuffix
Kousik Kumarc75e1292022-07-07 02:20:51 +0000152 expConfigFetcher := &smpb.ExpConfigFetcher{Filename: &configName}
David Goldsmith62243a32022-04-08 13:42:04 +0000153 defer func() {
154 ctx.Metrics.ExpConfigFetcher(expConfigFetcher)
155 }()
Kousik Kumarc75e1292022-07-07 02:20:51 +0000156 if !config.GoogleProdCredsExist() {
157 status := smpb.ExpConfigFetcher_MISSING_GCERT
158 expConfigFetcher.Status = &status
159 return nil
160 }
David Goldsmith62243a32022-04-08 13:42:04 +0000161
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500162 s, err := os.Stat(configFetcher)
163 if err != nil {
164 if os.IsNotExist(err) {
165 return nil
166 }
167 return err
168 }
169 if s.Mode()&0111 == 0 {
David Goldsmith62243a32022-04-08 13:42:04 +0000170 status := smpb.ExpConfigFetcher_ERROR
171 expConfigFetcher.Status = &status
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500172 return fmt.Errorf("configuration fetcher binary %v is not executable: %v", configFetcher, s.Mode())
173 }
174
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500175 tCtx, cancel := context.WithTimeout(ctx, envConfigFetchTimeout)
176 defer cancel()
David Goldsmith62243a32022-04-08 13:42:04 +0000177 fetchStart := time.Now()
178 cmd := exec.CommandContext(tCtx, configFetcher, "-output_config_dir", config.OutDir(),
179 "-output_config_name", configName)
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500180 if err := cmd.Start(); err != nil {
David Goldsmith62243a32022-04-08 13:42:04 +0000181 status := smpb.ExpConfigFetcher_ERROR
182 expConfigFetcher.Status = &status
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500183 return err
184 }
185
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500186 if err := cmd.Wait(); err != nil {
David Goldsmith62243a32022-04-08 13:42:04 +0000187 status := smpb.ExpConfigFetcher_ERROR
188 expConfigFetcher.Status = &status
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500189 return err
190 }
David Goldsmith62243a32022-04-08 13:42:04 +0000191 fetchEnd := time.Now()
192 expConfigFetcher.Micros = proto.Uint64(uint64(fetchEnd.Sub(fetchStart).Microseconds()))
193 outConfigFilePath := filepath.Join(config.OutDir(), configName)
194 expConfigFetcher.Filename = proto.String(outConfigFilePath)
195 if _, err := os.Stat(outConfigFilePath); err == nil {
196 status := smpb.ExpConfigFetcher_CONFIG
197 expConfigFetcher.Status = &status
198 } else {
199 status := smpb.ExpConfigFetcher_NO_CONFIG
200 expConfigFetcher.Status = &status
201 }
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500202 return nil
203}
204
205func loadEnvConfig(ctx Context, config *configImpl) error {
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500206 bc := os.Getenv("ANDROID_BUILD_ENVIRONMENT_CONFIG")
207 if bc == "" {
208 return nil
209 }
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500210
211 if err := fetchEnvConfig(ctx, config, bc); err != nil {
Kousik Kumar595fb1c2022-06-24 16:49:52 +0000212 ctx.Verbosef("Failed to fetch config file: %v\n", err)
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500213 }
214
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500215 configDirs := []string{
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500216 config.OutDir(),
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500217 os.Getenv("ANDROID_BUILD_ENVIRONMENT_CONFIG_DIR"),
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500218 envConfigDir,
219 }
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500220 for _, dir := range configDirs {
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500221 cfgFile := filepath.Join(os.Getenv("TOP"), dir, fmt.Sprintf("%s.%s", bc, jsonSuffix))
222 envVarsJSON, err := ioutil.ReadFile(cfgFile)
223 if err != nil {
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500224 continue
225 }
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500226 ctx.Verbosef("Loading config file %v\n", cfgFile)
227 var envVars map[string]map[string]string
228 if err := json.Unmarshal(envVarsJSON, &envVars); err != nil {
229 fmt.Fprintf(os.Stderr, "Env vars config file %s did not parse correctly: %s", cfgFile, err.Error())
230 continue
231 }
232 for k, v := range envVars["env"] {
233 if os.Getenv(k) != "" {
234 continue
235 }
236 config.environ.Set(k, v)
237 }
238 ctx.Verbosef("Finished loading config file %v\n", cfgFile)
239 break
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500240 }
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500241
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500242 return nil
243}
244
Chris Parsonsb6e96902022-10-31 20:08:45 -0400245func defaultBazelProdMode(cfg *configImpl) bool {
MarkDacekd06db5d2022-11-29 00:47:59 +0000246 // Environment flag to disable Bazel for users which experience
Chris Parsonsb6e96902022-10-31 20:08:45 -0400247 // broken bazel-handled builds, or significant performance regressions.
248 if cfg.IsBazelMixedBuildForceDisabled() {
249 return false
250 }
251 // Darwin-host builds are currently untested with Bazel.
252 if runtime.GOOS == "darwin" {
253 return false
254 }
Chris Parsons035e03a2022-11-01 14:25:45 -0400255 return true
Chris Parsonsb6e96902022-10-31 20:08:45 -0400256}
257
Dan Willemsen1e704462016-08-21 15:17:17 -0700258func NewConfig(ctx Context, args ...string) Config {
259 ret := &configImpl{
Spandan Dasa3639e62021-05-25 19:14:02 +0000260 environ: OsEnvironment(),
261 sandboxConfig: &SandboxConfig{},
Dan Willemsen1e704462016-08-21 15:17:17 -0700262 }
263
Patrice Arruda90109172020-07-28 18:07:27 +0000264 // Default matching ninja
Dan Willemsen9b587492017-07-10 22:13:00 -0700265 ret.parallel = runtime.NumCPU() + 2
266 ret.keepGoing = 1
267
Dan Willemsen2bb82d02019-12-27 09:35:42 -0800268 ret.totalRAM = detectTotalRAM(ctx)
269
Dan Willemsen9b587492017-07-10 22:13:00 -0700270 ret.parseArgs(ctx, args)
271
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800272 // Make sure OUT_DIR is set appropriately
Dan Willemsen02f3add2017-05-12 13:50:19 -0700273 if outDir, ok := ret.environ.Get("OUT_DIR"); ok {
274 ret.environ.Set("OUT_DIR", filepath.Clean(outDir))
275 } else {
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800276 outDir := "out"
277 if baseDir, ok := ret.environ.Get("OUT_DIR_COMMON_BASE"); ok {
278 if wd, err := os.Getwd(); err != nil {
279 ctx.Fatalln("Failed to get working directory:", err)
280 } else {
281 outDir = filepath.Join(baseDir, filepath.Base(wd))
282 }
283 }
284 ret.environ.Set("OUT_DIR", outDir)
285 }
286
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500287 // loadEnvConfig needs to know what the OUT_DIR is, so it should
288 // be called after we determine the appropriate out directory.
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500289 if err := loadEnvConfig(ctx, ret); err != nil {
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500290 ctx.Fatalln("Failed to parse env config files: %v", err)
291 }
292
Dan Willemsen2d31a442018-10-20 21:33:41 -0700293 if distDir, ok := ret.environ.Get("DIST_DIR"); ok {
294 ret.distDir = filepath.Clean(distDir)
295 } else {
296 ret.distDir = filepath.Join(ret.OutDir(), "dist")
297 }
Dan Willemsend50e89f2018-10-16 17:49:25 -0700298
Spandan Das05063612021-06-25 01:39:04 +0000299 if srcDirIsWritable, ok := ret.environ.Get("BUILD_BROKEN_SRC_DIR_IS_WRITABLE"); ok {
300 ret.sandboxConfig.SetSrcDirIsRO(srcDirIsWritable == "false")
301 }
302
Dan Willemsen1e704462016-08-21 15:17:17 -0700303 ret.environ.Unset(
304 // We're already using it
305 "USE_SOONG_UI",
306
307 // We should never use GOROOT/GOPATH from the shell environment
308 "GOROOT",
309 "GOPATH",
310
311 // These should only come from Soong, not the environment.
312 "CLANG",
313 "CLANG_CXX",
314 "CCC_CC",
315 "CCC_CXX",
316
317 // Used by the goma compiler wrapper, but should only be set by
318 // gomacc
319 "GOMACC_PATH",
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800320
321 // We handle this above
322 "OUT_DIR_COMMON_BASE",
Dan Willemsen68a09852017-04-18 13:56:57 -0700323
Dan Willemsen2d31a442018-10-20 21:33:41 -0700324 // This is handled above too, and set for individual commands later
325 "DIST_DIR",
326
Dan Willemsen68a09852017-04-18 13:56:57 -0700327 // Variables that have caused problems in the past
Dan Willemsen1c504d92019-11-18 19:13:53 +0000328 "BASH_ENV",
Dan Willemsenebfe33a2018-05-01 10:07:50 -0700329 "CDPATH",
Dan Willemsen68a09852017-04-18 13:56:57 -0700330 "DISPLAY",
331 "GREP_OPTIONS",
Dan Willemsenebfe33a2018-05-01 10:07:50 -0700332 "NDK_ROOT",
Dan Willemsen00fcb262018-08-15 15:35:38 -0700333 "POSIXLY_CORRECT",
Dan Willemsenc40e10b2017-07-11 14:30:00 -0700334
335 // Drop make flags
336 "MAKEFLAGS",
337 "MAKELEVEL",
338 "MFLAGS",
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700339
340 // Set in envsetup.sh, reset in makefiles
341 "ANDROID_JAVA_TOOLCHAIN",
Colin Cross7f09c402018-07-11 14:49:31 -0700342
343 // Set by envsetup.sh, but shouldn't be used inside the build because envsetup.sh is optional
344 "ANDROID_BUILD_TOP",
345 "ANDROID_HOST_OUT",
346 "ANDROID_PRODUCT_OUT",
347 "ANDROID_HOST_OUT_TESTCASES",
348 "ANDROID_TARGET_OUT_TESTCASES",
349 "ANDROID_TOOLCHAIN",
350 "ANDROID_TOOLCHAIN_2ND_ARCH",
351 "ANDROID_DEV_SCRIPTS",
352 "ANDROID_EMULATOR_PREBUILTS",
353 "ANDROID_PRE_BUILD_PATHS",
Dan Willemsen1e704462016-08-21 15:17:17 -0700354 )
355
Kousik Kumarb328f6d2020-10-19 01:45:46 -0400356 if ret.UseGoma() || ret.ForceUseGoma() {
357 ctx.Println("Goma for Android has been deprecated and replaced with RBE. See go/rbe_for_android for instructions on how to use RBE.")
358 ctx.Fatalln("USE_GOMA / FORCE_USE_GOMA flag is no longer supported.")
Kousik Kumarec478642020-09-21 13:39:24 -0400359 }
360
Dan Willemsen1e704462016-08-21 15:17:17 -0700361 // Tell python not to spam the source tree with .pyc files.
362 ret.environ.Set("PYTHONDONTWRITEBYTECODE", "1")
363
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400364 tmpDir := absPath(ctx, ret.TempDir())
365 ret.environ.Set("TMPDIR", tmpDir)
Dan Willemsen32a669b2018-03-08 19:42:00 -0800366
Dan Willemsen70c1ff82019-08-21 14:56:13 -0700367 // Always set ASAN_SYMBOLIZER_PATH so that ASAN-based tools can symbolize any crashes
368 symbolizerPath := filepath.Join("prebuilts/clang/host", ret.HostPrebuiltTag(),
369 "llvm-binutils-stable/llvm-symbolizer")
370 ret.environ.Set("ASAN_SYMBOLIZER_PATH", absPath(ctx, symbolizerPath))
371
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800372 // Precondition: the current directory is the top of the source tree
Patrice Arruda13848222019-04-22 17:12:02 -0700373 checkTopDir(ctx)
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800374
Yu Liu6e13b402021-07-27 14:29:06 -0700375 srcDir := absPath(ctx, ".")
376 if strings.ContainsRune(srcDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700377 ctx.Println("You are building in a directory whose absolute path contains a space character:")
378 ctx.Println()
379 ctx.Printf("%q\n", srcDir)
380 ctx.Println()
381 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700382 }
383
Yu Liu6e13b402021-07-27 14:29:06 -0700384 ret.metricsUploader = GetMetricsUploader(srcDir, ret.environ)
385
Dan Willemsendb8457c2017-05-12 16:38:17 -0700386 if outDir := ret.OutDir(); strings.ContainsRune(outDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700387 ctx.Println("The absolute path of your output directory ($OUT_DIR) contains a space character:")
388 ctx.Println()
389 ctx.Printf("%q\n", outDir)
390 ctx.Println()
391 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700392 }
393
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000394 if distDir := ret.RealDistDir(); strings.ContainsRune(distDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700395 ctx.Println("The absolute path of your dist directory ($DIST_DIR) contains a space character:")
396 ctx.Println()
397 ctx.Printf("%q\n", distDir)
398 ctx.Println()
399 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700400 }
401
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700402 // Configure Java-related variables, including adding it to $PATH
Tobias Thierere59aeff2017-12-20 22:40:39 +0000403 java8Home := filepath.Join("prebuilts/jdk/jdk8", ret.HostPrebuiltTag())
404 java9Home := filepath.Join("prebuilts/jdk/jdk9", ret.HostPrebuiltTag())
Pete Gillin1f52e932019-10-09 17:10:08 +0100405 java11Home := filepath.Join("prebuilts/jdk/jdk11", ret.HostPrebuiltTag())
Colin Cross59c1e6a2022-03-04 13:37:19 -0800406 java17Home := filepath.Join("prebuilts/jdk/jdk17", ret.HostPrebuiltTag())
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700407 javaHome := func() string {
408 if override, ok := ret.environ.Get("OVERRIDE_ANDROID_JAVA_HOME"); ok {
409 return override
410 }
Pete Gillina7a3d642019-11-07 18:58:42 +0000411 if toolchain11, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN"); ok && toolchain11 != "true" {
412 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 +0100413 }
Sorin Basca7e094b32022-10-05 08:20:12 +0000414 if toolchain17, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN"); ok && toolchain17 != "true" {
415 ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN is no longer supported. An OpenJDK 17 toolchain is now the global default.")
416 }
417 return java17Home
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700418 }()
419 absJavaHome := absPath(ctx, javaHome)
420
Dan Willemsened869522018-01-08 14:58:46 -0800421 ret.configureLocale(ctx)
422
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700423 newPath := []string{filepath.Join(absJavaHome, "bin")}
424 if path, ok := ret.environ.Get("PATH"); ok && path != "" {
425 newPath = append(newPath, path)
426 }
Pete Gillin1f52e932019-10-09 17:10:08 +0100427
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700428 ret.environ.Unset("OVERRIDE_ANDROID_JAVA_HOME")
429 ret.environ.Set("JAVA_HOME", absJavaHome)
430 ret.environ.Set("ANDROID_JAVA_HOME", javaHome)
Tobias Thierere59aeff2017-12-20 22:40:39 +0000431 ret.environ.Set("ANDROID_JAVA8_HOME", java8Home)
432 ret.environ.Set("ANDROID_JAVA9_HOME", java9Home)
Pete Gillin1f52e932019-10-09 17:10:08 +0100433 ret.environ.Set("ANDROID_JAVA11_HOME", java11Home)
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700434 ret.environ.Set("PATH", strings.Join(newPath, string(filepath.ListSeparator)))
435
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800436 outDir := ret.OutDir()
437 buildDateTimeFile := filepath.Join(outDir, "build_date.txt")
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800438 if buildDateTime, ok := ret.environ.Get("BUILD_DATETIME"); ok && buildDateTime != "" {
Colin Cross28f527c2019-11-26 16:19:04 -0800439 ret.buildDateTime = buildDateTime
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800440 } else {
Colin Cross28f527c2019-11-26 16:19:04 -0800441 ret.buildDateTime = strconv.FormatInt(time.Now().Unix(), 10)
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800442 }
Colin Cross28f527c2019-11-26 16:19:04 -0800443
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800444 ret.environ.Set("BUILD_DATETIME_FILE", buildDateTimeFile)
445
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400446 if ret.UseRBE() {
Ramy Medhat0fc67eb2020-08-12 01:26:23 -0400447 for k, v := range getRBEVars(ctx, Config{ret}) {
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400448 ret.environ.Set(k, v)
449 }
450 }
451
Patrice Arruda83842d72020-12-08 19:42:08 +0000452 bpd := ret.BazelMetricsDir()
Patrice Arrudaaf880da2020-11-13 08:41:26 -0800453 if err := os.RemoveAll(bpd); err != nil {
454 ctx.Fatalf("Unable to remove bazel profile directory %q: %v", bpd, err)
455 }
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000456
Patrice Arruda96850362020-08-11 20:41:11 +0000457 c := Config{ret}
458 storeConfigMetrics(ctx, c)
459 return c
Dan Willemsen9b587492017-07-10 22:13:00 -0700460}
461
Patrice Arruda13848222019-04-22 17:12:02 -0700462// NewBuildActionConfig returns a build configuration based on the build action. The arguments are
463// processed based on the build action and extracts any arguments that belongs to the build action.
Dan Willemsence41e942019-07-29 23:39:30 -0700464func NewBuildActionConfig(action BuildAction, dir string, ctx Context, args ...string) Config {
465 return NewConfig(ctx, getConfigArgs(action, dir, ctx, args)...)
Patrice Arruda13848222019-04-22 17:12:02 -0700466}
467
Patrice Arruda96850362020-08-11 20:41:11 +0000468// storeConfigMetrics selects a set of configuration information and store in
469// the metrics system for further analysis.
470func storeConfigMetrics(ctx Context, config Config) {
471 if ctx.Metrics == nil {
472 return
473 }
474
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400475 ctx.Metrics.BuildConfig(buildConfig(config))
Patrice Arruda3edfd482020-10-13 23:58:41 +0000476
477 s := &smpb.SystemResourceInfo{
478 TotalPhysicalMemory: proto.Uint64(config.TotalRAM()),
479 AvailableCpus: proto.Int32(int32(runtime.NumCPU())),
480 }
481 ctx.Metrics.SystemResourceInfo(s)
Patrice Arruda96850362020-08-11 20:41:11 +0000482}
483
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400484func buildConfig(config Config) *smpb.BuildConfig {
Yu Liue737a992021-10-04 13:21:41 -0700485 c := &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -0400486 ForceUseGoma: proto.Bool(config.ForceUseGoma()),
487 UseGoma: proto.Bool(config.UseGoma()),
488 UseRbe: proto.Bool(config.UseRBE()),
489 BazelMixedBuild: proto.Bool(config.BazelBuildEnabled()),
490 ForceDisableBazelMixedBuild: proto.Bool(config.IsBazelMixedBuildForceDisabled()),
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400491 }
Yu Liue737a992021-10-04 13:21:41 -0700492 c.Targets = append(c.Targets, config.arguments...)
493
494 return c
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400495}
496
Patrice Arruda13848222019-04-22 17:12:02 -0700497// getConfigArgs processes the command arguments based on the build action and creates a set of new
498// arguments to be accepted by Config.
Dan Willemsence41e942019-07-29 23:39:30 -0700499func getConfigArgs(action BuildAction, dir string, ctx Context, args []string) []string {
Patrice Arruda13848222019-04-22 17:12:02 -0700500 // The next block of code verifies that the current directory is the root directory of the source
501 // tree. It then finds the relative path of dir based on the root directory of the source tree
502 // and verify that dir is inside of the source tree.
503 checkTopDir(ctx)
504 topDir, err := os.Getwd()
505 if err != nil {
506 ctx.Fatalf("Error retrieving top directory: %v", err)
507 }
Patrice Arrudababa9a92019-07-03 10:47:34 -0700508 dir, err = filepath.EvalSymlinks(dir)
509 if err != nil {
510 ctx.Fatalf("Unable to evaluate symlink of %s: %v", dir, err)
511 }
Patrice Arruda13848222019-04-22 17:12:02 -0700512 dir, err = filepath.Abs(dir)
513 if err != nil {
514 ctx.Fatalf("Unable to find absolute path %s: %v", dir, err)
515 }
516 relDir, err := filepath.Rel(topDir, dir)
517 if err != nil {
518 ctx.Fatalf("Unable to find relative path %s of %s: %v", relDir, topDir, err)
519 }
520 // If there are ".." in the path, it's not in the source tree.
521 if strings.Contains(relDir, "..") {
522 ctx.Fatalf("Directory %s is not under the source tree %s", dir, topDir)
523 }
524
525 configArgs := args[:]
526
527 // If the arguments contains GET-INSTALL-PATH, change the target name prefix from MODULES-IN- to
528 // GET-INSTALL-PATH-IN- to extract the installation path instead of building the modules.
529 targetNamePrefix := "MODULES-IN-"
530 if inList("GET-INSTALL-PATH", configArgs) {
531 targetNamePrefix = "GET-INSTALL-PATH-IN-"
532 configArgs = removeFromList("GET-INSTALL-PATH", configArgs)
533 }
534
Patrice Arruda13848222019-04-22 17:12:02 -0700535 var targets []string
536
537 switch action {
Patrice Arruda39282062019-06-20 16:35:12 -0700538 case BUILD_MODULES:
539 // No additional processing is required when building a list of specific modules or all modules.
Patrice Arruda13848222019-04-22 17:12:02 -0700540 case BUILD_MODULES_IN_A_DIRECTORY:
541 // If dir is the root source tree, all the modules are built of the source tree are built so
542 // no need to find the build file.
543 if topDir == dir {
544 break
545 }
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700546
Patrice Arruda13848222019-04-22 17:12:02 -0700547 buildFile := findBuildFile(ctx, relDir)
548 if buildFile == "" {
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700549 ctx.Fatalf("Build file not found for %s directory", relDir)
Patrice Arruda13848222019-04-22 17:12:02 -0700550 }
Patrice Arruda13848222019-04-22 17:12:02 -0700551 targets = []string{convertToTarget(filepath.Dir(buildFile), targetNamePrefix)}
552 case BUILD_MODULES_IN_DIRECTORIES:
553 newConfigArgs, dirs := splitArgs(configArgs)
554 configArgs = newConfigArgs
Dan Willemsence41e942019-07-29 23:39:30 -0700555 targets = getTargetsFromDirs(ctx, relDir, dirs, targetNamePrefix)
Patrice Arruda13848222019-04-22 17:12:02 -0700556 }
557
558 // Tidy only override all other specified targets.
559 tidyOnly := os.Getenv("WITH_TIDY_ONLY")
560 if tidyOnly == "true" || tidyOnly == "1" {
561 configArgs = append(configArgs, "tidy_only")
562 } else {
563 configArgs = append(configArgs, targets...)
564 }
565
566 return configArgs
567}
568
569// convertToTarget replaces "/" to "-" in dir and pre-append the targetNamePrefix to the target name.
570func convertToTarget(dir string, targetNamePrefix string) string {
571 return targetNamePrefix + strings.ReplaceAll(dir, "/", "-")
572}
573
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700574// hasBuildFile returns true if dir contains an Android build file.
575func hasBuildFile(ctx Context, dir string) bool {
576 for _, buildFile := range buildFiles {
577 _, err := os.Stat(filepath.Join(dir, buildFile))
578 if err == nil {
579 return true
580 }
581 if !os.IsNotExist(err) {
582 ctx.Fatalf("Error retrieving the build file stats: %v", err)
583 }
584 }
585 return false
586}
587
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700588// findBuildFile finds a build file (makefile or blueprint file) by looking if there is a build file
589// in the current and any sub directory of dir. If a build file is not found, traverse the path
590// up by one directory and repeat again until either a build file is found or reached to the root
591// source tree. The returned filename of build file is "Android.mk". If one was not found, a blank
592// string is returned.
Patrice Arruda13848222019-04-22 17:12:02 -0700593func findBuildFile(ctx Context, dir string) string {
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700594 // If the string is empty or ".", assume it is top directory of the source tree.
595 if dir == "" || dir == "." {
Patrice Arruda13848222019-04-22 17:12:02 -0700596 return ""
597 }
598
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700599 found := false
600 for buildDir := dir; buildDir != "."; buildDir = filepath.Dir(buildDir) {
601 err := filepath.Walk(buildDir, func(path string, info os.FileInfo, err error) error {
602 if err != nil {
603 return err
604 }
605 if found {
606 return filepath.SkipDir
607 }
608 if info.IsDir() {
609 return nil
610 }
611 for _, buildFile := range buildFiles {
612 if info.Name() == buildFile {
613 found = true
614 return filepath.SkipDir
615 }
616 }
617 return nil
618 })
619 if err != nil {
620 ctx.Fatalf("Error finding Android build file: %v", err)
621 }
622
623 if found {
624 return filepath.Join(buildDir, "Android.mk")
Patrice Arruda13848222019-04-22 17:12:02 -0700625 }
626 }
627
628 return ""
629}
630
631// splitArgs iterates over the arguments list and splits into two lists: arguments and directories.
632func splitArgs(args []string) (newArgs []string, dirs []string) {
633 specialArgs := map[string]bool{
634 "showcommands": true,
635 "snod": true,
636 "dist": true,
637 "checkbuild": true,
638 }
639
640 newArgs = []string{}
641 dirs = []string{}
642
643 for _, arg := range args {
644 // It's a dash argument if it starts with "-" or it's a key=value pair, it's not a directory.
645 if strings.IndexRune(arg, '-') == 0 || strings.IndexRune(arg, '=') != -1 {
646 newArgs = append(newArgs, arg)
647 continue
648 }
649
650 if _, ok := specialArgs[arg]; ok {
651 newArgs = append(newArgs, arg)
652 continue
653 }
654
655 dirs = append(dirs, arg)
656 }
657
658 return newArgs, dirs
659}
660
661// getTargetsFromDirs iterates over the dirs list and creates a list of targets to build. If a
662// directory from the dirs list does not exist, a fatal error is raised. relDir is related to the
663// source root tree where the build action command was invoked. Each directory is validated if the
664// build file can be found and follows the format "dir1:target1,target2,...". Target is optional.
Dan Willemsence41e942019-07-29 23:39:30 -0700665func getTargetsFromDirs(ctx Context, relDir string, dirs []string, targetNamePrefix string) (targets []string) {
Patrice Arruda13848222019-04-22 17:12:02 -0700666 for _, dir := range dirs {
667 // The directory may have specified specific modules to build. ":" is the separator to separate
668 // the directory and the list of modules.
669 s := strings.Split(dir, ":")
670 l := len(s)
671 if l > 2 { // more than one ":" was specified.
672 ctx.Fatalf("%s not in proper directory:target1,target2,... format (\":\" was specified more than once)", dir)
673 }
674
675 dir = filepath.Join(relDir, s[0])
676 if _, err := os.Stat(dir); err != nil {
677 ctx.Fatalf("couldn't find directory %s", dir)
678 }
679
680 // Verify that if there are any targets specified after ":". Each target is separated by ",".
681 var newTargets []string
682 if l == 2 && s[1] != "" {
683 newTargets = strings.Split(s[1], ",")
684 if inList("", newTargets) {
685 ctx.Fatalf("%s not in proper directory:target1,target2,... format", dir)
686 }
687 }
688
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700689 // If there are specified targets to build in dir, an android build file must exist for the one
690 // shot build. For the non-targets case, find the appropriate build file and build all the
691 // modules in dir (or the closest one in the dir path).
Patrice Arruda13848222019-04-22 17:12:02 -0700692 if len(newTargets) > 0 {
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700693 if !hasBuildFile(ctx, dir) {
Patrice Arruda13848222019-04-22 17:12:02 -0700694 ctx.Fatalf("Couldn't locate a build file from %s directory", dir)
695 }
696 } else {
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700697 buildFile := findBuildFile(ctx, dir)
698 if buildFile == "" {
699 ctx.Fatalf("Build file not found for %s directory", dir)
700 }
701 newTargets = []string{convertToTarget(filepath.Dir(buildFile), targetNamePrefix)}
Patrice Arruda13848222019-04-22 17:12:02 -0700702 }
703
Patrice Arruda13848222019-04-22 17:12:02 -0700704 targets = append(targets, newTargets...)
705 }
706
Dan Willemsence41e942019-07-29 23:39:30 -0700707 return targets
Patrice Arruda13848222019-04-22 17:12:02 -0700708}
709
Dan Willemsen9b587492017-07-10 22:13:00 -0700710func (c *configImpl) parseArgs(ctx Context, args []string) {
711 for i := 0; i < len(args); i++ {
712 arg := strings.TrimSpace(args[i])
Anton Hansson5a7861a2021-06-04 10:09:01 +0100713 if arg == "showcommands" {
Dan Willemsen9b587492017-07-10 22:13:00 -0700714 c.verbose = true
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200715 } else if arg == "--empty-ninja-file" {
716 c.emptyNinjaFile = true
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100717 } else if arg == "--skip-ninja" {
718 c.skipNinja = true
Dan Willemsene0879fc2017-08-04 15:06:27 -0700719 } else if arg == "--skip-make" {
Colin Cross30e444b2021-06-18 11:26:19 -0700720 // TODO(ccross): deprecate this, it has confusing behaviors. It doesn't run kati,
721 // but it does run a Kati ninja file if the .kati_enabled marker file was created
722 // by a previous build.
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000723 c.skipConfig = true
724 c.skipKati = true
725 } else if arg == "--skip-kati" {
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100726 // TODO: remove --skip-kati once module builds have been migrated to --song-only
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000727 c.skipKati = true
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100728 } else if arg == "--soong-only" {
729 c.skipKati = true
730 c.skipKatiNinja = true
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200731 } else if arg == "--config-only" {
732 c.skipKati = true
733 c.skipKatiNinja = true
734 c.skipSoong = true
Colin Cross30e444b2021-06-18 11:26:19 -0700735 } else if arg == "--skip-config" {
736 c.skipConfig = true
Colin Cross00a8a3f2020-10-29 14:08:31 -0700737 } else if arg == "--skip-soong-tests" {
738 c.skipSoongTests = true
MarkDacekd0e7cd32022-12-02 22:22:40 +0000739 } else if arg == "--skip-metrics-upload" {
740 c.skipMetricsUpload = true
Chris Parsons53f68ae2022-03-03 12:01:40 -0500741 } else if arg == "--mk-metrics" {
742 c.reportMkMetrics = true
Chris Parsonsef615e52022-08-18 22:04:11 -0400743 } else if arg == "--bazel-mode" {
744 c.bazelProdMode = true
745 } else if arg == "--bazel-mode-dev" {
746 c.bazelDevMode = true
MarkDacekb78465d2022-10-18 20:10:16 +0000747 } else if arg == "--bazel-mode-staging" {
748 c.bazelStagingMode = true
Spandan Das394aa322022-11-03 17:02:10 +0000749 } else if arg == "--search-api-dir" {
750 c.searchApiDir = true
MarkDacekb96561e2022-12-02 04:34:43 +0000751 } else if strings.HasPrefix(arg, "--build-command=") {
752 buildCmd := strings.TrimPrefix(arg, "--build-command=")
753 // remove quotations
754 buildCmd = strings.TrimPrefix(buildCmd, "\"")
755 buildCmd = strings.TrimSuffix(buildCmd, "\"")
756 ctx.Metrics.SetBuildCommand([]string{buildCmd})
MarkDacekd06db5d2022-11-29 00:47:59 +0000757 } else if strings.HasPrefix(arg, "--bazel-force-enabled-modules=") {
758 c.bazelForceEnabledModules = strings.TrimPrefix(arg, "--bazel-force-enabled-modules=")
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700759 } else if len(arg) > 0 && arg[0] == '-' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700760 parseArgNum := func(def int) int {
761 if len(arg) > 2 {
762 p, err := strconv.ParseUint(arg[2:], 10, 31)
763 if err != nil {
764 ctx.Fatalf("Failed to parse %q: %v", arg, err)
765 }
766 return int(p)
767 } else if i+1 < len(args) {
768 p, err := strconv.ParseUint(args[i+1], 10, 31)
769 if err == nil {
770 i++
771 return int(p)
772 }
773 }
774 return def
775 }
776
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700777 if len(arg) > 1 && arg[1] == 'j' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700778 c.parallel = parseArgNum(c.parallel)
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700779 } else if len(arg) > 1 && arg[1] == 'k' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700780 c.keepGoing = parseArgNum(0)
Dan Willemsen1e704462016-08-21 15:17:17 -0700781 } else {
782 ctx.Fatalln("Unknown option:", arg)
783 }
Dan Willemsen091525e2017-07-11 14:17:50 -0700784 } else if k, v, ok := decodeKeyValue(arg); ok && len(k) > 0 {
Dan Willemsen6dfe30a2018-09-10 12:41:10 -0700785 if k == "OUT_DIR" {
786 ctx.Fatalln("OUT_DIR may only be set in the environment, not as a command line option.")
787 }
Dan Willemsen091525e2017-07-11 14:17:50 -0700788 c.environ.Set(k, v)
Dan Willemsen2d31a442018-10-20 21:33:41 -0700789 } else if arg == "dist" {
790 c.dist = true
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200791 } else if arg == "json-module-graph" {
792 c.jsonModuleGraph = true
793 } else if arg == "bp2build" {
794 c.bp2build = true
Spandan Das5af0bd32022-09-28 20:43:08 +0000795 } else if arg == "api_bp2build" {
796 c.apiBp2build = true
Lukacs T. Berki3a821692021-09-06 17:08:02 +0200797 } else if arg == "queryview" {
798 c.queryview = true
Lukacs T. Berkic6012f32021-09-06 18:31:46 +0200799 } else if arg == "soong_docs" {
800 c.soongDocs = true
Dan Willemsen1e704462016-08-21 15:17:17 -0700801 } else {
Dan Willemsen2d31a442018-10-20 21:33:41 -0700802 if arg == "checkbuild" {
Colin Cross37193492017-11-16 17:55:00 -0800803 c.checkbuild = true
Dan Willemsene0879fc2017-08-04 15:06:27 -0700804 }
Dan Willemsen9b587492017-07-10 22:13:00 -0700805 c.arguments = append(c.arguments, arg)
Dan Willemsen1e704462016-08-21 15:17:17 -0700806 }
807 }
Chris Parsonsb6e96902022-10-31 20:08:45 -0400808 if (!c.bazelProdMode) && (!c.bazelDevMode) && (!c.bazelStagingMode) {
809 c.bazelProdMode = defaultBazelProdMode(c)
810 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700811}
812
Dan Willemsened869522018-01-08 14:58:46 -0800813func (c *configImpl) configureLocale(ctx Context) {
814 cmd := Command(ctx, Config{c}, "locale", "locale", "-a")
815 output, err := cmd.Output()
816
817 var locales []string
818 if err == nil {
819 locales = strings.Split(string(output), "\n")
820 } else {
821 // If we're unable to list the locales, let's assume en_US.UTF-8
822 locales = []string{"en_US.UTF-8"}
823 ctx.Verbosef("Failed to list locales (%q), falling back to %q", err, locales)
824 }
825
826 // gettext uses LANGUAGE, which is passed directly through
827
828 // For LANG and LC_*, only preserve the evaluated version of
829 // LC_MESSAGES
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800830 userLang := ""
Dan Willemsened869522018-01-08 14:58:46 -0800831 if lc_all, ok := c.environ.Get("LC_ALL"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800832 userLang = lc_all
Dan Willemsened869522018-01-08 14:58:46 -0800833 } else if lc_messages, ok := c.environ.Get("LC_MESSAGES"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800834 userLang = lc_messages
Dan Willemsened869522018-01-08 14:58:46 -0800835 } else if lang, ok := c.environ.Get("LANG"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800836 userLang = lang
Dan Willemsened869522018-01-08 14:58:46 -0800837 }
838
839 c.environ.UnsetWithPrefix("LC_")
840
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800841 if userLang != "" {
842 c.environ.Set("LC_MESSAGES", userLang)
Dan Willemsened869522018-01-08 14:58:46 -0800843 }
844
845 // The for LANG, use C.UTF-8 if it exists (Debian currently, proposed
846 // for others)
847 if inList("C.UTF-8", locales) {
848 c.environ.Set("LANG", "C.UTF-8")
Aaron Klingd236e0e2018-08-07 19:21:36 -0500849 } else if inList("C.utf8", locales) {
850 // These normalize to the same thing
851 c.environ.Set("LANG", "C.UTF-8")
Dan Willemsened869522018-01-08 14:58:46 -0800852 } else if inList("en_US.UTF-8", locales) {
853 c.environ.Set("LANG", "en_US.UTF-8")
854 } else if inList("en_US.utf8", locales) {
855 // These normalize to the same thing
856 c.environ.Set("LANG", "en_US.UTF-8")
857 } else {
858 ctx.Fatalln("System doesn't support either C.UTF-8 or en_US.UTF-8")
859 }
860}
861
Dan Willemsen1e704462016-08-21 15:17:17 -0700862func (c *configImpl) Environment() *Environment {
863 return c.environ
864}
865
866func (c *configImpl) Arguments() []string {
867 return c.arguments
868}
869
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200870func (c *configImpl) SoongBuildInvocationNeeded() bool {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200871 if len(c.Arguments()) > 0 {
872 // Explicit targets requested that are not special targets like b2pbuild
873 // or the JSON module graph
874 return true
875 }
876
Spandan Das5af0bd32022-09-28 20:43:08 +0000877 if !c.JsonModuleGraph() && !c.Bp2Build() && !c.Queryview() && !c.SoongDocs() && !c.ApiBp2build() {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200878 // Command line was empty, the default Ninja target is built
879 return true
880 }
881
Liz Kammer88677422021-12-15 15:03:19 -0500882 // bp2build + dist may be used to dist bp2build logs but does not require SoongBuildInvocation
883 if c.Dist() && !c.Bp2Build() {
884 return true
885 }
886
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200887 // build.ninja doesn't need to be generated
888 return false
889}
890
Dan Willemsen1e704462016-08-21 15:17:17 -0700891func (c *configImpl) OutDir() string {
892 if outDir, ok := c.environ.Get("OUT_DIR"); ok {
Patrice Arruda19bd53e2019-07-08 17:26:47 -0700893 return outDir
Dan Willemsen1e704462016-08-21 15:17:17 -0700894 }
895 return "out"
896}
897
Dan Willemsen8a073a82017-02-04 17:30:44 -0800898func (c *configImpl) DistDir() string {
Chris Parsons19ab9a42022-08-30 13:15:04 -0400899 return c.distDir
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000900}
901
902func (c *configImpl) RealDistDir() string {
Dan Willemsen2d31a442018-10-20 21:33:41 -0700903 return c.distDir
Dan Willemsen8a073a82017-02-04 17:30:44 -0800904}
905
Dan Willemsen1e704462016-08-21 15:17:17 -0700906func (c *configImpl) NinjaArgs() []string {
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000907 if c.skipKati {
Dan Willemsene0879fc2017-08-04 15:06:27 -0700908 return c.arguments
909 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700910 return c.ninjaArgs
911}
912
Jingwen Chen7c6089a2020-11-02 02:56:20 -0500913func (c *configImpl) BazelOutDir() string {
914 return filepath.Join(c.OutDir(), "bazel")
915}
916
Liz Kammer2af5ea82022-11-11 14:21:03 -0500917func (c *configImpl) bazelOutputBase() string {
918 return filepath.Join(c.BazelOutDir(), "output")
919}
920
Dan Willemsen1e704462016-08-21 15:17:17 -0700921func (c *configImpl) SoongOutDir() string {
922 return filepath.Join(c.OutDir(), "soong")
923}
924
Spandan Das394aa322022-11-03 17:02:10 +0000925func (c *configImpl) ApiSurfacesOutDir() string {
926 return filepath.Join(c.OutDir(), "api_surfaces")
927}
928
Lukacs T. Berkia806e412021-09-01 08:57:48 +0200929func (c *configImpl) PrebuiltOS() string {
930 switch runtime.GOOS {
931 case "linux":
932 return "linux-x86"
933 case "darwin":
934 return "darwin-x86"
935 default:
936 panic("Unknown GOOS")
937 }
938}
Lukacs T. Berki90b43342021-11-02 14:42:04 +0100939
Lukacs T. Berkia806e412021-09-01 08:57:48 +0200940func (c *configImpl) HostToolDir() string {
Colin Crossacfcc1f2021-10-25 15:40:32 -0700941 if c.SkipKatiNinja() {
942 return filepath.Join(c.SoongOutDir(), "host", c.PrebuiltOS(), "bin")
943 } else {
944 return filepath.Join(c.OutDir(), "host", c.PrebuiltOS(), "bin")
945 }
Lukacs T. Berkia806e412021-09-01 08:57:48 +0200946}
947
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200948func (c *configImpl) NamedGlobFile(name string) string {
Lukacs T. Berki90b43342021-11-02 14:42:04 +0100949 return shared.JoinPath(c.SoongOutDir(), "globs-"+name+".ninja")
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200950}
951
Lukacs T. Berkie1df43f2021-09-08 15:31:14 +0200952func (c *configImpl) UsedEnvFile(tag string) string {
953 return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+tag)
954}
955
Lukacs T. Berkic541cd22022-10-26 07:26:50 +0000956func (c *configImpl) Bp2BuildFilesMarkerFile() string {
957 return shared.JoinPath(c.SoongOutDir(), "bp2build_files_marker")
958}
959
960func (c *configImpl) Bp2BuildWorkspaceMarkerFile() string {
Lukacs T. Berki90b43342021-11-02 14:42:04 +0100961 return shared.JoinPath(c.SoongOutDir(), "bp2build_workspace_marker")
Lukacs T. Berki56ebaf32021-08-12 14:03:55 +0200962}
963
Lukacs T. Berkic6012f32021-09-06 18:31:46 +0200964func (c *configImpl) SoongDocsHtml() string {
965 return shared.JoinPath(c.SoongOutDir(), "docs/soong_build.html")
966}
967
Lukacs T. Berki3a821692021-09-06 17:08:02 +0200968func (c *configImpl) QueryviewMarkerFile() string {
969 return shared.JoinPath(c.SoongOutDir(), "queryview.marker")
970}
971
Spandan Das5af0bd32022-09-28 20:43:08 +0000972func (c *configImpl) ApiBp2buildMarkerFile() string {
973 return shared.JoinPath(c.SoongOutDir(), "api_bp2build.marker")
974}
975
Lukacs T. Berkie571dc32021-08-25 14:14:13 +0200976func (c *configImpl) ModuleGraphFile() string {
977 return shared.JoinPath(c.SoongOutDir(), "module-graph.json")
978}
979
kgui67007242022-01-25 13:50:25 +0800980func (c *configImpl) ModuleActionsFile() string {
981 return shared.JoinPath(c.SoongOutDir(), "module-actions.json")
982}
983
Jeff Gastonefc1b412017-03-29 17:29:06 -0700984func (c *configImpl) TempDir() string {
985 return shared.TempDirForOutDir(c.SoongOutDir())
986}
987
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700988func (c *configImpl) FileListDir() string {
989 return filepath.Join(c.OutDir(), ".module_paths")
990}
991
Dan Willemsen1e704462016-08-21 15:17:17 -0700992func (c *configImpl) KatiSuffix() string {
993 if c.katiSuffix != "" {
994 return c.katiSuffix
995 }
996 panic("SetKatiSuffix has not been called")
997}
998
Colin Cross37193492017-11-16 17:55:00 -0800999// Checkbuild returns true if "checkbuild" was one of the build goals, which means that the
1000// user is interested in additional checks at the expense of build time.
1001func (c *configImpl) Checkbuild() bool {
1002 return c.checkbuild
1003}
1004
Dan Willemsen8a073a82017-02-04 17:30:44 -08001005func (c *configImpl) Dist() bool {
1006 return c.dist
1007}
1008
Lukacs T. Berkia1b93722021-09-02 17:23:06 +02001009func (c *configImpl) JsonModuleGraph() bool {
1010 return c.jsonModuleGraph
1011}
1012
1013func (c *configImpl) Bp2Build() bool {
1014 return c.bp2build
1015}
1016
Spandan Das5af0bd32022-09-28 20:43:08 +00001017func (c *configImpl) ApiBp2build() bool {
1018 return c.apiBp2build
1019}
1020
Lukacs T. Berki3a821692021-09-06 17:08:02 +02001021func (c *configImpl) Queryview() bool {
1022 return c.queryview
1023}
1024
Lukacs T. Berkic6012f32021-09-06 18:31:46 +02001025func (c *configImpl) SoongDocs() bool {
1026 return c.soongDocs
1027}
1028
Dan Willemsen1e704462016-08-21 15:17:17 -07001029func (c *configImpl) IsVerbose() bool {
1030 return c.verbose
1031}
1032
Anton Hansson5e5c48b2020-11-27 12:35:20 +00001033func (c *configImpl) SkipKati() bool {
1034 return c.skipKati
1035}
1036
Anton Hansson0b55bdb2021-06-04 10:08:08 +01001037func (c *configImpl) SkipKatiNinja() bool {
1038 return c.skipKatiNinja
1039}
1040
Lukacs T. Berkicef87b62021-08-10 15:01:13 +02001041func (c *configImpl) SkipSoong() bool {
1042 return c.skipSoong
1043}
1044
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +01001045func (c *configImpl) SkipNinja() bool {
1046 return c.skipNinja
1047}
1048
Anton Hansson5a7861a2021-06-04 10:09:01 +01001049func (c *configImpl) SetSkipNinja(v bool) {
1050 c.skipNinja = v
1051}
1052
Anton Hansson5e5c48b2020-11-27 12:35:20 +00001053func (c *configImpl) SkipConfig() bool {
1054 return c.skipConfig
Dan Willemsene0879fc2017-08-04 15:06:27 -07001055}
1056
Dan Willemsen1e704462016-08-21 15:17:17 -07001057func (c *configImpl) TargetProduct() string {
1058 if v, ok := c.environ.Get("TARGET_PRODUCT"); ok {
1059 return v
1060 }
1061 panic("TARGET_PRODUCT is not defined")
1062}
1063
Dan Willemsen02781d52017-05-12 19:28:13 -07001064func (c *configImpl) TargetDevice() string {
1065 return c.targetDevice
1066}
1067
1068func (c *configImpl) SetTargetDevice(device string) {
1069 c.targetDevice = device
1070}
1071
1072func (c *configImpl) TargetBuildVariant() string {
1073 if v, ok := c.environ.Get("TARGET_BUILD_VARIANT"); ok {
1074 return v
1075 }
1076 panic("TARGET_BUILD_VARIANT is not defined")
1077}
1078
Dan Willemsen1e704462016-08-21 15:17:17 -07001079func (c *configImpl) KatiArgs() []string {
1080 return c.katiArgs
1081}
1082
1083func (c *configImpl) Parallel() int {
1084 return c.parallel
1085}
1086
Spandan Dasc5763832022-11-08 18:42:16 +00001087func (c *configImpl) GetIncludeTags() []string {
1088 return c.includeTags
1089}
1090
1091func (c *configImpl) SetIncludeTags(i []string) {
1092 c.includeTags = i
1093}
1094
Colin Cross8b8bec32019-11-15 13:18:43 -08001095func (c *configImpl) HighmemParallel() int {
1096 if i, ok := c.environ.GetInt("NINJA_HIGHMEM_NUM_JOBS"); ok {
1097 return i
1098 }
1099
1100 const minMemPerHighmemProcess = 8 * 1024 * 1024 * 1024
1101 parallel := c.Parallel()
1102 if c.UseRemoteBuild() {
1103 // Ninja doesn't support nested pools, and when remote builds are enabled the total ninja parallelism
1104 // is set very high (i.e. 500). Using a large value here would cause the total number of running jobs
1105 // to be the sum of the sizes of the local and highmem pools, which will cause extra CPU contention.
1106 // Return 1/16th of the size of the local pool, rounding up.
1107 return (parallel + 15) / 16
1108 } else if c.totalRAM == 0 {
1109 // Couldn't detect the total RAM, don't restrict highmem processes.
1110 return parallel
Dan Willemsen570a2922020-05-26 23:02:29 -07001111 } else if c.totalRAM <= 16*1024*1024*1024 {
1112 // Less than 16GB of ram, restrict to 1 highmem processes
1113 return 1
Colin Cross8b8bec32019-11-15 13:18:43 -08001114 } else if c.totalRAM <= 32*1024*1024*1024 {
1115 // Less than 32GB of ram, restrict to 2 highmem processes
1116 return 2
1117 } else if p := int(c.totalRAM / minMemPerHighmemProcess); p < parallel {
1118 // If less than 8GB total RAM per process, reduce the number of highmem processes
1119 return p
1120 }
1121 // No restriction on highmem processes
1122 return parallel
1123}
1124
Dan Willemsen2bb82d02019-12-27 09:35:42 -08001125func (c *configImpl) TotalRAM() uint64 {
1126 return c.totalRAM
1127}
1128
Kousik Kumarec478642020-09-21 13:39:24 -04001129// ForceUseGoma determines whether we should override Goma deprecation
1130// and use Goma for the current build or not.
1131func (c *configImpl) ForceUseGoma() bool {
1132 if v, ok := c.environ.Get("FORCE_USE_GOMA"); ok {
1133 v = strings.TrimSpace(v)
1134 if v != "" && v != "false" {
1135 return true
1136 }
1137 }
1138 return false
1139}
1140
Dan Willemsen1e704462016-08-21 15:17:17 -07001141func (c *configImpl) UseGoma() bool {
1142 if v, ok := c.environ.Get("USE_GOMA"); ok {
1143 v = strings.TrimSpace(v)
1144 if v != "" && v != "false" {
1145 return true
1146 }
1147 }
1148 return false
1149}
1150
Yoshisato Yanagisawa2cb0e5d2019-01-10 10:14:16 +09001151func (c *configImpl) StartGoma() bool {
1152 if !c.UseGoma() {
1153 return false
1154 }
1155
1156 if v, ok := c.environ.Get("NOSTART_GOMA"); ok {
1157 v = strings.TrimSpace(v)
1158 if v != "" && v != "false" {
1159 return false
1160 }
1161 }
1162 return true
1163}
1164
Ramy Medhatbbf25672019-07-17 12:30:04 +00001165func (c *configImpl) UseRBE() bool {
Kousik Kumar3ff037e2022-01-25 22:11:01 -05001166 if v, ok := c.Environment().Get("USE_RBE"); ok {
Ramy Medhatbbf25672019-07-17 12:30:04 +00001167 v = strings.TrimSpace(v)
1168 if v != "" && v != "false" {
1169 return true
1170 }
1171 }
1172 return false
1173}
1174
Chris Parsonsef615e52022-08-18 22:04:11 -04001175func (c *configImpl) BazelBuildEnabled() bool {
MarkDacekb78465d2022-10-18 20:10:16 +00001176 return c.bazelProdMode || c.bazelDevMode || c.bazelStagingMode
Chris Parsonsec1a3dc2021-04-20 15:32:07 -04001177}
1178
Ramy Medhatbbf25672019-07-17 12:30:04 +00001179func (c *configImpl) StartRBE() bool {
1180 if !c.UseRBE() {
1181 return false
1182 }
1183
1184 if v, ok := c.environ.Get("NOSTART_RBE"); ok {
1185 v = strings.TrimSpace(v)
1186 if v != "" && v != "false" {
1187 return false
1188 }
1189 }
1190 return true
1191}
1192
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001193func (c *configImpl) rbeProxyLogsDir() string {
1194 for _, f := range []string{"RBE_proxy_log_dir", "FLAG_output_dir"} {
Kousik Kumar0d15a722020-09-23 02:54:11 -04001195 if v, ok := c.environ.Get(f); ok {
1196 return v
1197 }
1198 }
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001199 buildTmpDir := shared.TempDirForOutDir(c.SoongOutDir())
1200 return filepath.Join(buildTmpDir, "rbe")
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001201}
1202
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001203func (c *configImpl) shouldCleanupRBELogsDir() bool {
1204 // Perform a log directory cleanup only when the log directory
1205 // is auto created by the build rather than user-specified.
1206 for _, f := range []string{"RBE_proxy_log_dir", "FLAG_output_dir"} {
1207 if _, ok := c.environ.Get(f); ok {
1208 return false
Patrice Arruda62f1bf22020-07-07 12:48:26 +00001209 }
1210 }
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001211 return true
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001212}
1213
1214func (c *configImpl) rbeExecRoot() string {
1215 for _, f := range []string{"RBE_exec_root", "FLAG_exec_root"} {
1216 if v, ok := c.environ.Get(f); ok {
1217 return v
1218 }
1219 }
1220 wd, err := os.Getwd()
1221 if err != nil {
1222 return ""
1223 }
1224 return wd
1225}
1226
1227func (c *configImpl) rbeDir() string {
1228 if v, ok := c.environ.Get("RBE_DIR"); ok {
1229 return v
1230 }
1231 return "prebuilts/remoteexecution-client/live/"
1232}
1233
1234func (c *configImpl) rbeReproxy() string {
1235 for _, f := range []string{"RBE_re_proxy", "FLAG_re_proxy"} {
1236 if v, ok := c.environ.Get(f); ok {
1237 return v
1238 }
1239 }
1240 return filepath.Join(c.rbeDir(), "reproxy")
1241}
1242
1243func (c *configImpl) rbeAuth() (string, string) {
Kousik Kumar93d192c2022-03-18 01:39:56 -04001244 credFlags := []string{
1245 "use_application_default_credentials",
1246 "use_gce_credentials",
1247 "credential_file",
1248 "use_google_prod_creds",
1249 }
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001250 for _, cf := range credFlags {
1251 for _, f := range []string{"RBE_" + cf, "FLAG_" + cf} {
1252 if v, ok := c.environ.Get(f); ok {
1253 v = strings.TrimSpace(v)
1254 if v != "" && v != "false" && v != "0" {
1255 return "RBE_" + cf, v
1256 }
1257 }
1258 }
1259 }
1260 return "RBE_use_application_default_credentials", "true"
Patrice Arruda62f1bf22020-07-07 12:48:26 +00001261}
1262
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001263func (c *configImpl) rbeSockAddr(dir string) (string, error) {
1264 maxNameLen := len(syscall.RawSockaddrUnix{}.Path)
1265 base := fmt.Sprintf("reproxy_%v.sock", rbeRandPrefix)
1266
1267 name := filepath.Join(dir, base)
1268 if len(name) < maxNameLen {
1269 return name, nil
1270 }
1271
1272 name = filepath.Join("/tmp", base)
1273 if len(name) < maxNameLen {
1274 return name, nil
1275 }
1276
1277 return "", fmt.Errorf("cannot generate a proxy socket address shorter than the limit of %v", maxNameLen)
1278}
1279
Kousik Kumar7bc78192022-04-27 14:52:56 -04001280// IsGooglerEnvironment returns true if the current build is running
1281// on a Google developer machine and false otherwise.
1282func (c *configImpl) IsGooglerEnvironment() bool {
1283 cf := "ANDROID_BUILD_ENVIRONMENT_CONFIG"
1284 if v, ok := c.environ.Get(cf); ok {
1285 return v == "googler"
1286 }
1287 return false
1288}
1289
1290// GoogleProdCredsExist determine whether credentials exist on the
1291// Googler machine to use remote execution.
1292func (c *configImpl) GoogleProdCredsExist() bool {
1293 if _, err := exec.Command("/usr/bin/prodcertstatus", "--simple_output", "--nocheck_loas").Output(); err != nil {
1294 return false
1295 }
1296 return true
1297}
1298
1299// UseRemoteBuild indicates whether to use a remote build acceleration system
1300// to speed up the build.
Colin Cross9016b912019-11-11 14:57:42 -08001301func (c *configImpl) UseRemoteBuild() bool {
1302 return c.UseGoma() || c.UseRBE()
1303}
1304
Kousik Kumar7bc78192022-04-27 14:52:56 -04001305// StubbyExists checks whether the stubby binary exists on the machine running
1306// the build.
1307func (c *configImpl) StubbyExists() bool {
1308 if _, err := exec.LookPath("stubby"); err != nil {
1309 return false
1310 }
1311 return true
1312}
1313
Dan Willemsen1e704462016-08-21 15:17:17 -07001314// RemoteParallel controls how many remote jobs (i.e., commands which contain
Jeff Gastonefc1b412017-03-29 17:29:06 -07001315// gomacc) are run in parallel. Note the parallelism of all other jobs is
Dan Willemsen1e704462016-08-21 15:17:17 -07001316// still limited by Parallel()
1317func (c *configImpl) RemoteParallel() int {
Colin Cross8b8bec32019-11-15 13:18:43 -08001318 if !c.UseRemoteBuild() {
1319 return 0
1320 }
1321 if i, ok := c.environ.GetInt("NINJA_REMOTE_NUM_JOBS"); ok {
1322 return i
Dan Willemsen1e704462016-08-21 15:17:17 -07001323 }
1324 return 500
1325}
1326
1327func (c *configImpl) SetKatiArgs(args []string) {
1328 c.katiArgs = args
1329}
1330
1331func (c *configImpl) SetNinjaArgs(args []string) {
1332 c.ninjaArgs = args
1333}
1334
1335func (c *configImpl) SetKatiSuffix(suffix string) {
1336 c.katiSuffix = suffix
1337}
1338
Dan Willemsene0879fc2017-08-04 15:06:27 -07001339func (c *configImpl) LastKatiSuffixFile() string {
1340 return filepath.Join(c.OutDir(), "last_kati_suffix")
1341}
1342
1343func (c *configImpl) HasKatiSuffix() bool {
1344 return c.katiSuffix != ""
1345}
1346
Dan Willemsen1e704462016-08-21 15:17:17 -07001347func (c *configImpl) KatiEnvFile() string {
1348 return filepath.Join(c.OutDir(), "env"+c.KatiSuffix()+".sh")
1349}
1350
Dan Willemsen29971232018-09-26 14:58:30 -07001351func (c *configImpl) KatiBuildNinjaFile() string {
1352 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiBuildSuffix+".ninja")
Dan Willemsen1e704462016-08-21 15:17:17 -07001353}
1354
Dan Willemsenfb1271a2018-09-26 15:00:42 -07001355func (c *configImpl) KatiPackageNinjaFile() string {
1356 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiPackageSuffix+".ninja")
1357}
1358
Jihoon Kang9f4f8a32022-08-16 00:57:30 +00001359func (c *configImpl) SoongVarsFile() string {
1360 return filepath.Join(c.SoongOutDir(), "soong.variables")
1361}
1362
Dan Willemsen1e704462016-08-21 15:17:17 -07001363func (c *configImpl) SoongNinjaFile() string {
1364 return filepath.Join(c.SoongOutDir(), "build.ninja")
1365}
1366
1367func (c *configImpl) CombinedNinjaFile() string {
Dan Willemsene0879fc2017-08-04 15:06:27 -07001368 if c.katiSuffix == "" {
1369 return filepath.Join(c.OutDir(), "combined.ninja")
1370 }
Dan Willemsen1e704462016-08-21 15:17:17 -07001371 return filepath.Join(c.OutDir(), "combined"+c.KatiSuffix()+".ninja")
1372}
1373
1374func (c *configImpl) SoongAndroidMk() string {
1375 return filepath.Join(c.SoongOutDir(), "Android-"+c.TargetProduct()+".mk")
1376}
1377
1378func (c *configImpl) SoongMakeVarsMk() string {
1379 return filepath.Join(c.SoongOutDir(), "make_vars-"+c.TargetProduct()+".mk")
1380}
1381
Dan Willemsenf052f782017-05-18 15:29:04 -07001382func (c *configImpl) ProductOut() string {
Dan Willemsen4dc4e142017-09-08 14:35:43 -07001383 return filepath.Join(c.OutDir(), "target", "product", c.TargetDevice())
Dan Willemsenf052f782017-05-18 15:29:04 -07001384}
1385
Dan Willemsen02781d52017-05-12 19:28:13 -07001386func (c *configImpl) DevicePreviousProductConfig() string {
Dan Willemsenf052f782017-05-18 15:29:04 -07001387 return filepath.Join(c.ProductOut(), "previous_build_config.mk")
1388}
1389
Dan Willemsenfb1271a2018-09-26 15:00:42 -07001390func (c *configImpl) KatiPackageMkDir() string {
1391 return filepath.Join(c.ProductOut(), "obj", "CONFIG", "kati_packaging")
1392}
1393
Dan Willemsenf052f782017-05-18 15:29:04 -07001394func (c *configImpl) hostOutRoot() string {
Dan Willemsen4dc4e142017-09-08 14:35:43 -07001395 return filepath.Join(c.OutDir(), "host")
Dan Willemsenf052f782017-05-18 15:29:04 -07001396}
1397
1398func (c *configImpl) HostOut() string {
1399 return filepath.Join(c.hostOutRoot(), c.HostPrebuiltTag())
1400}
1401
1402// This probably needs to be multi-valued, so not exporting it for now
1403func (c *configImpl) hostCrossOut() string {
1404 if runtime.GOOS == "linux" {
1405 return filepath.Join(c.hostOutRoot(), "windows-x86")
1406 } else {
1407 return ""
1408 }
Dan Willemsen02781d52017-05-12 19:28:13 -07001409}
1410
Dan Willemsen1e704462016-08-21 15:17:17 -07001411func (c *configImpl) HostPrebuiltTag() string {
1412 if runtime.GOOS == "linux" {
1413 return "linux-x86"
1414 } else if runtime.GOOS == "darwin" {
1415 return "darwin-x86"
1416 } else {
1417 panic("Unsupported OS")
1418 }
1419}
Dan Willemsenf173d592017-04-27 14:28:00 -07001420
Dan Willemsen8122bd52017-10-12 20:20:41 -07001421func (c *configImpl) PrebuiltBuildTool(name string) string {
Dan Willemsenf173d592017-04-27 14:28:00 -07001422 if v, ok := c.environ.Get("SANITIZE_HOST"); ok {
1423 if sanitize := strings.Fields(v); inList("address", sanitize) {
Dan Willemsen8122bd52017-10-12 20:20:41 -07001424 asan := filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "asan/bin", name)
1425 if _, err := os.Stat(asan); err == nil {
1426 return asan
1427 }
Dan Willemsenf173d592017-04-27 14:28:00 -07001428 }
1429 }
1430 return filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "bin", name)
1431}
Dan Willemsen3d60b112018-04-04 22:25:56 -07001432
1433func (c *configImpl) SetBuildBrokenDupRules(val bool) {
1434 c.brokenDupRules = val
1435}
1436
1437func (c *configImpl) BuildBrokenDupRules() bool {
1438 return c.brokenDupRules
1439}
Dan Willemsen6ab79db2018-05-02 00:06:28 -07001440
Dan Willemsen25e6f092019-04-09 10:22:43 -07001441func (c *configImpl) SetBuildBrokenUsesNetwork(val bool) {
1442 c.brokenUsesNetwork = val
1443}
1444
1445func (c *configImpl) BuildBrokenUsesNetwork() bool {
1446 return c.brokenUsesNetwork
1447}
1448
Dan Willemsene3336352020-01-02 19:10:38 -08001449func (c *configImpl) SetBuildBrokenNinjaUsesEnvVars(val []string) {
1450 c.brokenNinjaEnvVars = val
1451}
1452
1453func (c *configImpl) BuildBrokenNinjaUsesEnvVars() []string {
1454 return c.brokenNinjaEnvVars
1455}
1456
Dan Willemsen6ab79db2018-05-02 00:06:28 -07001457func (c *configImpl) SetTargetDeviceDir(dir string) {
1458 c.targetDeviceDir = dir
1459}
1460
1461func (c *configImpl) TargetDeviceDir() string {
1462 return c.targetDeviceDir
1463}
Dan Willemsenfa42f3c2018-06-15 21:54:47 -07001464
Patrice Arruda219eef32020-06-01 17:29:30 +00001465func (c *configImpl) BuildDateTime() string {
1466 return c.buildDateTime
1467}
1468
1469func (c *configImpl) MetricsUploaderApp() string {
Yu Liu6e13b402021-07-27 14:29:06 -07001470 return c.metricsUploader
Patrice Arruda219eef32020-06-01 17:29:30 +00001471}
Patrice Arruda83842d72020-12-08 19:42:08 +00001472
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001473// LogsDir returns the absolute path to the logs directory where build log and
1474// metrics files are located. By default, the logs directory is the out
Patrice Arruda83842d72020-12-08 19:42:08 +00001475// directory. If the argument dist is specified, the logs directory
1476// is <dist_dir>/logs.
1477func (c *configImpl) LogsDir() string {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001478 dir := c.OutDir()
Patrice Arruda83842d72020-12-08 19:42:08 +00001479 if c.Dist() {
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +00001480 // 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 -05001481 dir = filepath.Join(c.RealDistDir(), "logs")
Patrice Arruda83842d72020-12-08 19:42:08 +00001482 }
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001483 absDir, err := filepath.Abs(dir)
1484 if err != nil {
1485 fmt.Fprintf(os.Stderr, "\nError making log dir '%s' absolute: %s\n", dir, err.Error())
1486 os.Exit(1)
1487 }
1488 return absDir
Patrice Arruda83842d72020-12-08 19:42:08 +00001489}
1490
1491// BazelMetricsDir returns the <logs dir>/bazel_metrics directory
1492// where the bazel profiles are located.
1493func (c *configImpl) BazelMetricsDir() string {
1494 return filepath.Join(c.LogsDir(), "bazel_metrics")
1495}
Colin Crossf3bdbcb2021-06-01 11:43:55 -07001496
Chris Parsons53f68ae2022-03-03 12:01:40 -05001497// MkFileMetrics returns the file path for make-related metrics.
1498func (c *configImpl) MkMetrics() string {
1499 return filepath.Join(c.LogsDir(), "mk_metrics.pb")
1500}
1501
Colin Crossf3bdbcb2021-06-01 11:43:55 -07001502func (c *configImpl) SetEmptyNinjaFile(v bool) {
1503 c.emptyNinjaFile = v
1504}
1505
1506func (c *configImpl) EmptyNinjaFile() bool {
1507 return c.emptyNinjaFile
1508}
Yu Liu6e13b402021-07-27 14:29:06 -07001509
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001510func (c *configImpl) IsBazelMixedBuildForceDisabled() bool {
1511 return c.Environment().IsEnvTrue("BUILD_BROKEN_DISABLE_BAZEL")
1512}
1513
MarkDacekd06db5d2022-11-29 00:47:59 +00001514func (c *configImpl) BazelModulesForceEnabledByFlag() string {
1515 return c.bazelForceEnabledModules
1516}
1517
MarkDacekd0e7cd32022-12-02 22:22:40 +00001518func (c *configImpl) SkipMetricsUpload() bool {
1519 return c.skipMetricsUpload
1520}
1521
Yu Liu6e13b402021-07-27 14:29:06 -07001522func GetMetricsUploader(topDir string, env *Environment) string {
1523 if p, ok := env.Get("METRICS_UPLOADER"); ok {
1524 metricsUploader := filepath.Join(topDir, p)
1525 if _, err := os.Stat(metricsUploader); err == nil {
1526 return metricsUploader
1527 }
1528 }
1529
1530 return ""
1531}