blob: 667f0c90b5a3e9516d78e01f73588c59156d98b7 [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 (
Colin Cross46b0c752023-10-27 14:56:12 -070018 "android/soong/ui/tracer"
Colin Cross9191df22021-10-29 13:11:32 -070019 "fmt"
Kousik Kumarca390b22023-10-04 04:14:28 +000020 "io/fs"
Dan Willemsen99a75cd2017-08-04 16:04:04 -070021 "os"
Dan Willemsen1e704462016-08-21 15:17:17 -070022 "path/filepath"
Dan Willemsen99a75cd2017-08-04 16:04:04 -070023 "strconv"
Usta Shrestha8dc8b0a2022-08-10 17:39:37 -040024 "strings"
Kousik Kumarca390b22023-10-04 04:14:28 +000025 "sync"
26 "sync/atomic"
Colin Crossaa9a2732023-10-27 10:54:27 -070027 "time"
Dan Willemsen99a75cd2017-08-04 16:04:04 -070028
Chris Parsons9402ca82023-02-23 17:28:06 -050029 "android/soong/bazel"
Dan Willemsen4591b642021-05-24 14:24:12 -070030 "android/soong/ui/metrics"
Colin Crossaa9a2732023-10-27 10:54:27 -070031 "android/soong/ui/metrics/metrics_proto"
Dan Willemsen4591b642021-05-24 14:24:12 -070032 "android/soong/ui/status"
33
34 "android/soong/shared"
35
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +010036 "github.com/google/blueprint"
37 "github.com/google/blueprint/bootstrap"
Dan Willemsen99a75cd2017-08-04 16:04:04 -070038 "github.com/google/blueprint/microfactory"
Colin Crossaa9a2732023-10-27 10:54:27 -070039
40 "google.golang.org/protobuf/proto"
Dan Willemsen1e704462016-08-21 15:17:17 -070041)
42
Lukacs T. Berkif8e24282021-04-14 10:31:00 +020043const (
44 availableEnvFile = "soong.environment.available"
45 usedEnvFile = "soong.environment.used"
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +020046
Lukacs T. Berkic541cd22022-10-26 07:26:50 +000047 soongBuildTag = "build"
48 bp2buildFilesTag = "bp2build_files"
49 bp2buildWorkspaceTag = "bp2build_workspace"
50 jsonModuleGraphTag = "modulegraph"
51 queryviewTag = "queryview"
Lukacs T. Berkic541cd22022-10-26 07:26:50 +000052 soongDocsTag = "soong_docs"
Colin Cross9191df22021-10-29 13:11:32 -070053
54 // bootstrapEpoch is used to determine if an incremental build is incompatible with the current
55 // version of bootstrap and needs cleaning before continuing the build. Increment this for
56 // incompatible changes, for example when moving the location of the bpglob binary that is
57 // executed during bootstrap before the primary builder has had a chance to update the path.
Lukacs T. Berki9985d9a2021-11-04 11:47:42 +010058 bootstrapEpoch = 1
Lukacs T. Berkif8e24282021-04-14 10:31:00 +020059)
60
Kousik Kumarca390b22023-10-04 04:14:28 +000061var (
62 // Used during parallel update of symlinks in out directory to reflect new
63 // TOP dir.
64 symlinkWg sync.WaitGroup
65 numFound, numUpdated uint32
66)
67
Sasha Smundak4cbe83a2022-11-28 17:02:40 -080068func writeEnvironmentFile(_ Context, envFile string, envDeps map[string]string) error {
Lukacs T. Berki7690c092021-02-26 14:27:36 +010069 data, err := shared.EnvFileContents(envDeps)
70 if err != nil {
71 return err
72 }
73
Sasha Smundak4cbe83a2022-11-28 17:02:40 -080074 return os.WriteFile(envFile, data, 0644)
Lukacs T. Berki7690c092021-02-26 14:27:36 +010075}
76
Rupert Shuttleworthb7d97102020-11-25 10:19:29 +000077// This uses Android.bp files and various tools to generate <builddir>/build.ninja.
78//
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +010079// However, the execution of <builddir>/build.ninja happens later in
80// build/soong/ui/build/build.go#Build()
Rupert Shuttleworthb7d97102020-11-25 10:19:29 +000081//
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +010082// We want to rely on as few prebuilts as possible, so we need to bootstrap
83// Soong. The process is as follows:
Rupert Shuttleworthb7d97102020-11-25 10:19:29 +000084//
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +010085// 1. We use "Microfactory", a simple tool to compile Go code, to build
86// first itself, then soong_ui from soong_ui.bash. This binary contains
87// parts of soong_build that are needed to build itself.
88// 2. This simplified version of soong_build then reads the Blueprint files
89// that describe itself and emits .bootstrap/build.ninja that describes
90// how to build its full version and use that to produce the final Ninja
91// file Soong emits.
92// 3. soong_ui executes .bootstrap/build.ninja
Rupert Shuttleworthb7d97102020-11-25 10:19:29 +000093//
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +010094// (After this, Kati is executed to parse the Makefiles, but that's not part of
95// bootstrapping Soong)
96
97// A tiny struct used to tell Blueprint that it's in bootstrap mode. It would
98// probably be nicer to use a flag in bootstrap.Args instead.
99type BlueprintConfig struct {
Lukacs T. Berkiea1a31c2021-09-02 09:58:09 +0200100 toolDir string
101 soongOutDir string
102 outDir string
103 runGoTests bool
Lukacs T. Berkiea1a31c2021-09-02 09:58:09 +0200104 debugCompilation bool
105 subninjas []string
106 primaryBuilderInvocations []bootstrap.PrimaryBuilderInvocation
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100107}
108
Lukacs T. Berkia806e412021-09-01 08:57:48 +0200109func (c BlueprintConfig) HostToolDir() string {
110 return c.toolDir
111}
112
Lukacs T. Berki9f6c24a2021-08-26 15:07:24 +0200113func (c BlueprintConfig) SoongOutDir() string {
114 return c.soongOutDir
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100115}
116
Lukacs T. Berki9f6c24a2021-08-26 15:07:24 +0200117func (c BlueprintConfig) OutDir() string {
118 return c.outDir
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100119}
120
Lukacs T. Berkiea1a31c2021-09-02 09:58:09 +0200121func (c BlueprintConfig) RunGoTests() bool {
122 return c.runGoTests
123}
124
Lukacs T. Berki5f6cb1d2021-03-17 15:03:14 +0100125func (c BlueprintConfig) DebugCompilation() bool {
126 return c.debugCompilation
127}
128
Lukacs T. Berkiea1a31c2021-09-02 09:58:09 +0200129func (c BlueprintConfig) Subninjas() []string {
130 return c.subninjas
131}
132
133func (c BlueprintConfig) PrimaryBuilderInvocations() []bootstrap.PrimaryBuilderInvocation {
134 return c.primaryBuilderInvocations
135}
136
Lukacs T. Berkie1df43f2021-09-08 15:31:14 +0200137func environmentArgs(config Config, tag string) []string {
Lukacs T. Berkif8e24282021-04-14 10:31:00 +0200138 return []string{
139 "--available_env", shared.JoinPath(config.SoongOutDir(), availableEnvFile),
Lukacs T. Berkie1df43f2021-09-08 15:31:14 +0200140 "--used_env", config.UsedEnvFile(tag),
Lukacs T. Berkif8e24282021-04-14 10:31:00 +0200141 }
142}
Spandan Das8f99ae62021-06-11 16:48:06 +0000143
Colin Cross9191df22021-10-29 13:11:32 -0700144func writeEmptyFile(ctx Context, path string) {
Spandan Das8f99ae62021-06-11 16:48:06 +0000145 err := os.MkdirAll(filepath.Dir(path), 0777)
146 if err != nil {
Colin Cross9191df22021-10-29 13:11:32 -0700147 ctx.Fatalf("Failed to create parent directories of empty file '%s': %s", path, err)
Spandan Das8f99ae62021-06-11 16:48:06 +0000148 }
149
Colin Cross9191df22021-10-29 13:11:32 -0700150 if exists, err := fileExists(path); err != nil {
151 ctx.Fatalf("Failed to check if file '%s' exists: %s", path, err)
152 } else if !exists {
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800153 err = os.WriteFile(path, nil, 0666)
Spandan Das8f99ae62021-06-11 16:48:06 +0000154 if err != nil {
Colin Cross9191df22021-10-29 13:11:32 -0700155 ctx.Fatalf("Failed to create empty file '%s': %s", path, err)
Spandan Das8f99ae62021-06-11 16:48:06 +0000156 }
157 }
158}
159
Colin Cross9191df22021-10-29 13:11:32 -0700160func fileExists(path string) (bool, error) {
161 if _, err := os.Stat(path); os.IsNotExist(err) {
162 return false, nil
163 } else if err != nil {
164 return false, err
165 }
166 return true, nil
167}
168
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800169type PrimaryBuilderFactory struct {
170 name string
171 description string
172 config Config
173 output string
174 specificArgs []string
175 debugPort string
176}
177
Jeongik Chaccf37002023-08-04 01:46:32 +0900178func getGlobPathName(config Config) string {
179 globPathName, ok := config.TargetProductOrErr()
180 if ok != nil {
181 globPathName = soongBuildTag
182 }
183 return globPathName
184}
185
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800186func (pb PrimaryBuilderFactory) primaryBuilderInvocation() bootstrap.PrimaryBuilderInvocation {
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200187 commonArgs := make([]string, 0, 0)
188
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800189 if !pb.config.skipSoongTests {
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200190 commonArgs = append(commonArgs, "-t")
191 }
192
LaMont Jones80f70352023-03-20 19:58:25 +0000193 if pb.config.multitreeBuild {
LaMont Jones52a72432023-03-09 18:19:35 +0000194 commonArgs = append(commonArgs, "--multitree-build")
195 }
Jihoon Kang2a929ad2023-06-08 19:02:07 +0000196 if pb.config.buildFromSourceStub {
197 commonArgs = append(commonArgs, "--build-from-source-stub")
Jihoon Kang1bff0342023-01-17 20:40:22 +0000198 }
LaMont Jones52a72432023-03-09 18:19:35 +0000199
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800200 commonArgs = append(commonArgs, "-l", filepath.Join(pb.config.FileListDir(), "Android.bp.list"))
Lukacs T. Berki13644272022-01-05 10:29:56 +0100201 invocationEnv := make(map[string]string)
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800202 if pb.debugPort != "" {
ustafb67fd12022-08-19 19:26:00 -0400203 //debug mode
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800204 commonArgs = append(commonArgs, "--delve_listen", pb.debugPort,
205 "--delve_path", shared.ResolveDelveBinary())
Lukacs T. Berki13644272022-01-05 10:29:56 +0100206 // GODEBUG=asyncpreemptoff=1 disables the preemption of goroutines. This
207 // is useful because the preemption happens by sending SIGURG to the OS
208 // thread hosting the goroutine in question and each signal results in
209 // work that needs to be done by Delve; it uses ptrace to debug the Go
210 // process and the tracer process must deal with every signal (it is not
211 // possible to selectively ignore SIGURG). This makes debugging slower,
212 // sometimes by an order of magnitude depending on luck.
213 // The original reason for adding async preemption to Go is here:
214 // https://github.com/golang/proposal/blob/master/design/24543-non-cooperative-preemption.md
215 invocationEnv["GODEBUG"] = "asyncpreemptoff=1"
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200216 }
217
ustafb67fd12022-08-19 19:26:00 -0400218 var allArgs []string
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800219 allArgs = append(allArgs, pb.specificArgs...)
Jeongik Chaccf37002023-08-04 01:46:32 +0900220 globPathName := pb.name
221 // Glob path for soong build would be separated per product target
222 if pb.name == soongBuildTag {
223 globPathName = getGlobPathName(pb.config)
224 }
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200225 allArgs = append(allArgs,
Jeongik Chaccf37002023-08-04 01:46:32 +0900226 "--globListDir", globPathName,
227 "--globFile", pb.config.NamedGlobFile(globPathName))
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200228
229 allArgs = append(allArgs, commonArgs...)
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800230 allArgs = append(allArgs, environmentArgs(pb.config, pb.name)...)
Sasha Smundakfaa97b72022-11-18 15:32:49 -0800231 if profileCpu := os.Getenv("SOONG_PROFILE_CPU"); profileCpu != "" {
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800232 allArgs = append(allArgs, "--cpuprofile", profileCpu+"."+pb.name)
Sasha Smundakfaa97b72022-11-18 15:32:49 -0800233 }
234 if profileMem := os.Getenv("SOONG_PROFILE_MEM"); profileMem != "" {
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800235 allArgs = append(allArgs, "--memprofile", profileMem+"."+pb.name)
Sasha Smundakfaa97b72022-11-18 15:32:49 -0800236 }
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200237 allArgs = append(allArgs, "Android.bp")
238
239 return bootstrap.PrimaryBuilderInvocation{
Jingwen Chen78fd87f2021-12-06 13:27:43 +0000240 Inputs: []string{"Android.bp"},
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800241 Outputs: []string{pb.output},
Jingwen Chen78fd87f2021-12-06 13:27:43 +0000242 Args: allArgs,
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800243 Description: pb.description,
Lukacs T. Berki2fad3412022-01-04 14:40:13 +0100244 // NB: Changing the value of this environment variable will not result in a
245 // rebuild. The bootstrap Ninja file will change, but apparently Ninja does
246 // not consider changing the pool specified in a statement a change that's
247 // worth rebuilding for.
248 Console: os.Getenv("SOONG_UNBUFFERED_OUTPUT") == "1",
Lukacs T. Berki13644272022-01-05 10:29:56 +0100249 Env: invocationEnv,
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200250 }
251}
252
Colin Cross9191df22021-10-29 13:11:32 -0700253// bootstrapEpochCleanup deletes files used by bootstrap during incremental builds across
254// incompatible changes. Incompatible changes are marked by incrementing the bootstrapEpoch
255// constant. A tree is considered out of date for the current epoch of the
256// .soong.bootstrap.epoch.<epoch> file doesn't exist.
257func bootstrapEpochCleanup(ctx Context, config Config) {
258 epochFile := fmt.Sprintf(".soong.bootstrap.epoch.%d", bootstrapEpoch)
259 epochPath := filepath.Join(config.SoongOutDir(), epochFile)
260 if exists, err := fileExists(epochPath); err != nil {
261 ctx.Fatalf("failed to check if bootstrap epoch file %q exists: %q", epochPath, err)
262 } else if !exists {
263 // The tree is out of date for the current epoch, delete files used by bootstrap
264 // and force the primary builder to rerun.
Kiyoung Kima37d9ba2023-04-19 13:13:45 +0900265 os.Remove(config.SoongNinjaFile())
Colin Cross9191df22021-10-29 13:11:32 -0700266 for _, globFile := range bootstrapGlobFileList(config) {
267 os.Remove(globFile)
268 }
269
270 // Mark the tree as up to date with the current epoch by writing the epoch marker file.
271 writeEmptyFile(ctx, epochPath)
272 }
273}
274
275func bootstrapGlobFileList(config Config) []string {
276 return []string{
Jeongik Chaccf37002023-08-04 01:46:32 +0900277 config.NamedGlobFile(getGlobPathName(config)),
Lukacs T. Berkic541cd22022-10-26 07:26:50 +0000278 config.NamedGlobFile(bp2buildFilesTag),
Colin Cross9191df22021-10-29 13:11:32 -0700279 config.NamedGlobFile(jsonModuleGraphTag),
280 config.NamedGlobFile(queryviewTag),
281 config.NamedGlobFile(soongDocsTag),
282 }
283}
284
Lukacs T. Berki56ebaf32021-08-12 14:03:55 +0200285func bootstrapBlueprint(ctx Context, config Config) {
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100286 ctx.BeginTrace(metrics.RunSoong, "blueprint bootstrap")
287 defer ctx.EndTrace()
288
Colin Cross9191df22021-10-29 13:11:32 -0700289 // Clean up some files for incremental builds across incompatible changes.
290 bootstrapEpochCleanup(ctx, config)
291
Kiyoung Kima37d9ba2023-04-19 13:13:45 +0900292 baseArgs := []string{"--soong_variables", config.SoongVarsFile()}
293
294 mainSoongBuildExtraArgs := append(baseArgs, "-o", config.SoongNinjaFile())
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200295 if config.EmptyNinjaFile() {
296 mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--empty-ninja-file")
Lukacs T. Berki745380c2021-04-12 12:07:44 +0200297 }
Chris Parsonsef615e52022-08-18 22:04:11 -0400298 if config.bazelProdMode {
299 mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--bazel-mode")
300 }
MarkDacekb78465d2022-10-18 20:10:16 +0000301 if config.bazelStagingMode {
302 mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--bazel-mode-staging")
303 }
Chris Parsons9402ca82023-02-23 17:28:06 -0500304 if config.IsPersistentBazelEnabled() {
305 mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--use-bazel-proxy")
306 }
MarkDacekd06db5d2022-11-29 00:47:59 +0000307 if len(config.bazelForceEnabledModules) > 0 {
308 mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--bazel-force-enabled-modules="+config.bazelForceEnabledModules)
309 }
LaMont Jones52a72432023-03-09 18:19:35 +0000310 if config.MultitreeBuild() {
311 mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--multitree-build")
312 }
Jihoon Kang2a929ad2023-06-08 19:02:07 +0000313 if config.buildFromSourceStub {
314 mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--build-from-source-stub")
Jihoon Kang1bff0342023-01-17 20:40:22 +0000315 }
MarkDacekf47e1422023-04-19 16:47:36 +0000316 if config.ensureAllowlistIntegrity {
317 mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--ensure-allowlist-integrity")
318 }
MarkDacekd06db5d2022-11-29 00:47:59 +0000319
Jingwen Chen78fd87f2021-12-06 13:27:43 +0000320 queryviewDir := filepath.Join(config.SoongOutDir(), "queryview")
Spandan Das5af0bd32022-09-28 20:43:08 +0000321
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800322 pbfs := []PrimaryBuilderFactory{
323 {
324 name: soongBuildTag,
325 description: fmt.Sprintf("analyzing Android.bp files and generating ninja file at %s", config.SoongNinjaFile()),
326 config: config,
327 output: config.SoongNinjaFile(),
328 specificArgs: mainSoongBuildExtraArgs,
Jingwen Chen78fd87f2021-12-06 13:27:43 +0000329 },
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800330 {
Kiyoung Kima37d9ba2023-04-19 13:13:45 +0900331 name: bp2buildFilesTag,
332 description: fmt.Sprintf("converting Android.bp files to BUILD files at %s/bp2build", config.SoongOutDir()),
333 config: config,
334 output: config.Bp2BuildFilesMarkerFile(),
335 specificArgs: append(baseArgs,
336 "--bp2build_marker", config.Bp2BuildFilesMarkerFile(),
337 ),
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800338 },
339 {
Kiyoung Kima37d9ba2023-04-19 13:13:45 +0900340 name: bp2buildWorkspaceTag,
341 description: "Creating Bazel symlink forest",
342 config: config,
343 output: config.Bp2BuildWorkspaceMarkerFile(),
344 specificArgs: append(baseArgs,
345 "--symlink_forest_marker", config.Bp2BuildWorkspaceMarkerFile(),
346 ),
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800347 },
348 {
349 name: jsonModuleGraphTag,
350 description: fmt.Sprintf("generating the Soong module graph at %s", config.ModuleGraphFile()),
351 config: config,
352 output: config.ModuleGraphFile(),
Kiyoung Kima37d9ba2023-04-19 13:13:45 +0900353 specificArgs: append(baseArgs,
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800354 "--module_graph_file", config.ModuleGraphFile(),
355 "--module_actions_file", config.ModuleActionsFile(),
Kiyoung Kima37d9ba2023-04-19 13:13:45 +0900356 ),
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800357 },
358 {
Kiyoung Kima37d9ba2023-04-19 13:13:45 +0900359 name: queryviewTag,
360 description: fmt.Sprintf("generating the Soong module graph as a Bazel workspace at %s", queryviewDir),
361 config: config,
362 output: config.QueryviewMarkerFile(),
363 specificArgs: append(baseArgs,
364 "--bazel_queryview_dir", queryviewDir,
365 ),
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800366 },
367 {
Kiyoung Kima37d9ba2023-04-19 13:13:45 +0900368 name: soongDocsTag,
369 description: fmt.Sprintf("generating Soong docs at %s", config.SoongDocsHtml()),
370 config: config,
371 output: config.SoongDocsHtml(),
372 specificArgs: append(baseArgs,
373 "--soong_docs", config.SoongDocsHtml(),
374 ),
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800375 },
376 }
377
378 // Figure out which invocations will be run under the debugger:
379 // * SOONG_DELVE if set specifies listening port
380 // * SOONG_DELVE_STEPS if set specifies specific invocations to be debugged, otherwise all are
381 debuggedInvocations := make(map[string]bool)
382 delvePort := os.Getenv("SOONG_DELVE")
383 if delvePort != "" {
384 if steps := os.Getenv("SOONG_DELVE_STEPS"); steps != "" {
385 var validSteps []string
386 for _, pbf := range pbfs {
387 debuggedInvocations[pbf.name] = false
388 validSteps = append(validSteps, pbf.name)
389
390 }
391 for _, step := range strings.Split(steps, ",") {
392 if _, ok := debuggedInvocations[step]; ok {
393 debuggedInvocations[step] = true
394 } else {
395 ctx.Fatalf("SOONG_DELVE_STEPS contains unknown soong_build step %s\n"+
396 "Valid steps are %v", step, validSteps)
397 }
398 }
399 } else {
400 // SOONG_DELVE_STEPS is not set, run all steps in the debugger
401 for _, pbf := range pbfs {
402 debuggedInvocations[pbf.name] = true
403 }
404 }
405 }
406
407 var invocations []bootstrap.PrimaryBuilderInvocation
408 for _, pbf := range pbfs {
409 if debuggedInvocations[pbf.name] {
410 pbf.debugPort = delvePort
411 }
412 pbi := pbf.primaryBuilderInvocation()
413 // Some invocations require adjustment:
414 switch pbf.name {
415 case soongBuildTag:
416 if config.BazelBuildEnabled() {
417 // Mixed builds call Bazel from soong_build and they therefore need the
418 // Bazel workspace to be available. Make that so by adding a dependency on
419 // the bp2build marker file to the action that invokes soong_build .
420 pbi.OrderOnlyInputs = append(pbi.OrderOnlyInputs, config.Bp2BuildWorkspaceMarkerFile())
421 }
422 case bp2buildWorkspaceTag:
423 pbi.Inputs = append(pbi.Inputs,
424 config.Bp2BuildFilesMarkerFile(),
425 filepath.Join(config.FileListDir(), "bazel.list"))
Wei Li2c9e8d62023-05-05 01:07:15 -0700426 case bp2buildFilesTag:
427 pbi.Inputs = append(pbi.Inputs, filepath.Join(config.FileListDir(), "METADATA.list"))
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800428 }
429 invocations = append(invocations, pbi)
430 }
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200431
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200432 // The glob .ninja files are subninja'd. However, they are generated during
433 // the build itself so we write an empty file if the file does not exist yet
434 // so that the subninja doesn't fail on clean builds
Colin Cross9191df22021-10-29 13:11:32 -0700435 for _, globFile := range bootstrapGlobFileList(config) {
436 writeEmptyFile(ctx, globFile)
Lukacs T. Berkif8e24282021-04-14 10:31:00 +0200437 }
438
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800439 blueprintArgs := bootstrap.Args{
440 ModuleListFile: filepath.Join(config.FileListDir(), "Android.bp.list"),
441 OutFile: shared.JoinPath(config.SoongOutDir(), "bootstrap.ninja"),
442 EmptyNinjaFile: false,
443 }
Lukacs T. Berkif8e24282021-04-14 10:31:00 +0200444
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100445 blueprintCtx := blueprint.NewContext()
Spandan Dasc5763832022-11-08 18:42:16 +0000446 blueprintCtx.AddIncludeTags(config.GetIncludeTags()...)
Sam Delmerico98a73292023-02-21 11:50:29 -0500447 blueprintCtx.AddSourceRootDirs(config.GetSourceRootDirs()...)
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100448 blueprintCtx.SetIgnoreUnknownModuleTypes(true)
449 blueprintConfig := BlueprintConfig{
Lukacs T. Berkie1df43f2021-09-08 15:31:14 +0200450 soongOutDir: config.SoongOutDir(),
451 toolDir: config.HostToolDir(),
452 outDir: config.OutDir(),
453 runGoTests: !config.skipSoongTests,
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200454 // If we want to debug soong_build, we need to compile it for debugging
Sasha Smundak4cbe83a2022-11-28 17:02:40 -0800455 debugCompilation: delvePort != "",
456 subninjas: bootstrapGlobFileList(config),
457 primaryBuilderInvocations: invocations,
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100458 }
459
usta5bb4a5d2022-08-24 12:53:46 -0400460 // since `bootstrap.ninja` is regenerated unconditionally, we ignore the deps, i.e. little
461 // reason to write a `bootstrap.ninja.d` file
Lukacs T. Berkic357c812023-06-20 09:30:06 +0000462 _, err := bootstrap.RunBlueprint(blueprintArgs, bootstrap.DoEverything, blueprintCtx, blueprintConfig)
463 if err != nil {
464 ctx.Fatal(err)
465 }
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100466}
467
Jason Wu2520f5e2023-05-30 19:45:36 -0400468func checkEnvironmentFile(ctx Context, currentEnv *Environment, envFile string) {
Lukacs T. Berkif8e24282021-04-14 10:31:00 +0200469 getenv := func(k string) string {
470 v, _ := currentEnv.Get(k)
471 return v
472 }
Lukacs T. Berkie1df43f2021-09-08 15:31:14 +0200473
Jason Wu2520f5e2023-05-30 19:45:36 -0400474 // Log the changed environment variables to ChangedEnvironmentVariable field
475 if stale, changedEnvironmentVariableList, _ := shared.StaleEnvFile(envFile, getenv); stale {
476 for _, changedEnvironmentVariable := range changedEnvironmentVariableList {
477 ctx.Metrics.AddChangedEnvironmentVariable(changedEnvironmentVariable)
478 }
Lukacs T. Berkif8e24282021-04-14 10:31:00 +0200479 os.Remove(envFile)
480 }
481}
482
Kousik Kumarca390b22023-10-04 04:14:28 +0000483func updateSymlinks(ctx Context, dir, prevCWD, cwd string) error {
484 defer symlinkWg.Done()
485
486 visit := func(path string, d fs.DirEntry, err error) error {
487 if d.IsDir() && path != dir {
488 symlinkWg.Add(1)
489 go updateSymlinks(ctx, path, prevCWD, cwd)
490 return filepath.SkipDir
491 }
492 f, err := d.Info()
493 if err != nil {
494 return err
495 }
496 // If the file is not a symlink, we don't have to update it.
497 if f.Mode()&os.ModeSymlink != os.ModeSymlink {
498 return nil
499 }
500
501 atomic.AddUint32(&numFound, 1)
502 target, err := os.Readlink(path)
503 if err != nil {
504 return err
505 }
506 if strings.HasPrefix(target, prevCWD) &&
507 (len(target) == len(prevCWD) || target[len(prevCWD)] == '/') {
508 target = filepath.Join(cwd, target[len(prevCWD):])
509 if err := os.Remove(path); err != nil {
510 return err
511 }
512 if err := os.Symlink(target, path); err != nil {
513 return err
514 }
515 atomic.AddUint32(&numUpdated, 1)
516 }
517 return nil
518 }
519
520 if err := filepath.WalkDir(dir, visit); err != nil {
521 return err
522 }
523 return nil
524}
525
526func fixOutDirSymlinks(ctx Context, config Config, outDir string) error {
527 cwd, err := os.Getwd()
528 if err != nil {
529 return err
530 }
531
532 // Record the .top as the very last thing in the function.
533 tf := filepath.Join(outDir, ".top")
534 defer func() {
535 if err := os.WriteFile(tf, []byte(cwd), 0644); err != nil {
536 fmt.Fprintf(os.Stderr, fmt.Sprintf("Unable to log CWD: %v", err))
537 }
538 }()
539
540 // Find the previous working directory if it was recorded.
541 var prevCWD string
542 pcwd, err := os.ReadFile(tf)
543 if err != nil {
544 if os.IsNotExist(err) {
545 // No previous working directory recorded, nothing to do.
546 return nil
547 }
548 return err
549 }
550 prevCWD = strings.Trim(string(pcwd), "\n")
551
552 if prevCWD == cwd {
553 // We are in the same source dir, nothing to update.
554 return nil
555 }
556
557 symlinkWg.Add(1)
558 if err := updateSymlinks(ctx, outDir, prevCWD, cwd); err != nil {
559 return err
560 }
561 symlinkWg.Wait()
562 ctx.Println(fmt.Sprintf("Updated %d/%d symlinks in dir %v", numUpdated, numFound, outDir))
563 return nil
564}
565
566func migrateOutputSymlinks(ctx Context, config Config) error {
567 // Figure out the real out directory ("out" could be a symlink).
568 outDir := config.OutDir()
569 s, err := os.Lstat(outDir)
570 if err != nil {
571 if os.IsNotExist(err) {
572 // No out dir exists, no symlinks to migrate.
573 return nil
574 }
575 return err
576 }
577 if s.Mode()&os.ModeSymlink == os.ModeSymlink {
578 target, err := filepath.EvalSymlinks(outDir)
579 if err != nil {
580 return err
581 }
582 outDir = target
583 }
584 return fixOutDirSymlinks(ctx, config, outDir)
585}
586
Dan Willemsen1e704462016-08-21 15:17:17 -0700587func runSoong(ctx Context, config Config) {
Nan Zhang17f27672018-12-12 16:01:49 -0800588 ctx.BeginTrace(metrics.RunSoong, "soong")
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700589 defer ctx.EndTrace()
590
Kousik Kumarca390b22023-10-04 04:14:28 +0000591 if err := migrateOutputSymlinks(ctx, config); err != nil {
592 ctx.Fatalf("failed to migrate output directory to current TOP dir: %v", err)
593 }
594
Lukacs T. Berki7690c092021-02-26 14:27:36 +0100595 // We have two environment files: .available is the one with every variable,
596 // .used with the ones that were actually used. The latter is used to
597 // determine whether Soong needs to be re-run since why re-run it if only
598 // unused variables were changed?
Lukacs T. Berkif8e24282021-04-14 10:31:00 +0200599 envFile := filepath.Join(config.SoongOutDir(), availableEnvFile)
Lukacs T. Berki7690c092021-02-26 14:27:36 +0100600
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100601 // This is done unconditionally, but does not take a measurable amount of time
Lukacs T. Berki56ebaf32021-08-12 14:03:55 +0200602 bootstrapBlueprint(ctx, config)
Dan Willemsen99a75cd2017-08-04 16:04:04 -0700603
Lukacs T. Berki7690c092021-02-26 14:27:36 +0100604 soongBuildEnv := config.Environment().Copy()
605 soongBuildEnv.Set("TOP", os.Getenv("TOP"))
Lukacs T. Berki7690c092021-02-26 14:27:36 +0100606 // For Bazel mixed builds.
Joe Onoratoba29f382022-10-24 06:38:11 -0700607 soongBuildEnv.Set("BAZEL_PATH", "./build/bazel/bin/bazel")
Chris Parsonsa9bef142022-09-28 15:07:46 -0400608 // Bazel's HOME var is set to an output subdirectory which doesn't exist. This
609 // prevents Bazel from file I/O in the actual user HOME directory.
610 soongBuildEnv.Set("BAZEL_HOME", absPath(ctx, filepath.Join(config.BazelOutDir(), "bazelhome")))
Liz Kammer2af5ea82022-11-11 14:21:03 -0500611 soongBuildEnv.Set("BAZEL_OUTPUT_BASE", config.bazelOutputBase())
Lukacs T. Berki7690c092021-02-26 14:27:36 +0100612 soongBuildEnv.Set("BAZEL_WORKSPACE", absPath(ctx, "."))
613 soongBuildEnv.Set("BAZEL_METRICS_DIR", config.BazelMetricsDir())
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -0500614 soongBuildEnv.Set("LOG_DIR", config.LogsDir())
Jingwen Chen3b13b612022-10-17 12:14:26 +0000615 soongBuildEnv.Set("BAZEL_DEPS_FILE", absPath(ctx, filepath.Join(config.BazelOutDir(), "bazel.list")))
Lukacs T. Berki7690c092021-02-26 14:27:36 +0100616
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100617 // For Soong bootstrapping tests
618 if os.Getenv("ALLOW_MISSING_DEPENDENCIES") == "true" {
619 soongBuildEnv.Set("ALLOW_MISSING_DEPENDENCIES", "true")
620 }
621
Paul Duffin5e85c662021-03-05 12:26:14 +0000622 err := writeEnvironmentFile(ctx, envFile, soongBuildEnv.AsMap())
623 if err != nil {
624 ctx.Fatalf("failed to write environment file %s: %s", envFile, err)
625 }
Lukacs T. Berki7690c092021-02-26 14:27:36 +0100626
Dan Willemsen99a75cd2017-08-04 16:04:04 -0700627 func() {
Nan Zhang17f27672018-12-12 16:01:49 -0800628 ctx.BeginTrace(metrics.RunSoong, "environment check")
Dan Willemsen99a75cd2017-08-04 16:04:04 -0700629 defer ctx.EndTrace()
630
Jason Wu2520f5e2023-05-30 19:45:36 -0400631 checkEnvironmentFile(ctx, soongBuildEnv, config.UsedEnvFile(soongBuildTag))
Lukacs T. Berkif8e24282021-04-14 10:31:00 +0200632
Chris Parsonsef615e52022-08-18 22:04:11 -0400633 if config.BazelBuildEnabled() || config.Bp2Build() {
Jason Wu2520f5e2023-05-30 19:45:36 -0400634 checkEnvironmentFile(ctx, soongBuildEnv, config.UsedEnvFile(bp2buildFilesTag))
Chris Parsonsb6d6fc92023-10-30 16:21:06 +0000635 } else {
636 // Remove bazel files in the event that bazel is disabled for the build.
637 // These files may have been left over from a previous bazel-enabled build.
638 cleanBazelFiles(config)
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200639 }
640
641 if config.JsonModuleGraph() {
Jason Wu2520f5e2023-05-30 19:45:36 -0400642 checkEnvironmentFile(ctx, soongBuildEnv, config.UsedEnvFile(jsonModuleGraphTag))
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200643 }
644
645 if config.Queryview() {
Jason Wu2520f5e2023-05-30 19:45:36 -0400646 checkEnvironmentFile(ctx, soongBuildEnv, config.UsedEnvFile(queryviewTag))
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200647 }
648
649 if config.SoongDocs() {
Jason Wu2520f5e2023-05-30 19:45:36 -0400650 checkEnvironmentFile(ctx, soongBuildEnv, config.UsedEnvFile(soongDocsTag))
Dan Willemsen99a75cd2017-08-04 16:04:04 -0700651 }
652 }()
653
Colin Cross9191df22021-10-29 13:11:32 -0700654 runMicrofactory(ctx, config, "bpglob", "github.com/google/blueprint/bootstrap/bpglob",
Sasha Smundak7ae80a72021-04-09 12:03:51 -0700655 map[string]string{"github.com/google/blueprint": "build/blueprint"})
Dan Willemsen5af1cbe2018-07-05 21:46:51 -0700656
usta49012ee2023-05-22 16:33:27 -0400657 ninja := func(targets ...string) {
658 ctx.BeginTrace(metrics.RunSoong, "bootstrap")
Dan Willemsen99a75cd2017-08-04 16:04:04 -0700659 defer ctx.EndTrace()
660
Chris Parsons9402ca82023-02-23 17:28:06 -0500661 if config.IsPersistentBazelEnabled() {
Chris Parsonsc83398f2023-05-31 18:41:41 +0000662 bazelProxy := bazel.NewProxyServer(ctx.Logger, config.OutDir(), filepath.Join(config.SoongOutDir(), "workspace"), config.GetBazeliskBazelVersion())
usta49012ee2023-05-22 16:33:27 -0400663 if err := bazelProxy.Start(); err != nil {
664 ctx.Fatalf("Failed to create bazel proxy")
665 }
Chris Parsons9402ca82023-02-23 17:28:06 -0500666 defer bazelProxy.Close()
667 }
668
Dan Willemsenb82471a2018-05-17 16:37:09 -0700669 fifo := filepath.Join(config.OutDir(), ".ninja_fifo")
Colin Crossb98d3bc2019-03-21 16:02:58 -0700670 nr := status.NewNinjaReader(ctx, ctx.Status.StartTool(), fifo)
671 defer nr.Close()
Dan Willemsenb82471a2018-05-17 16:37:09 -0700672
Lukacs T. Berki56ebaf32021-08-12 14:03:55 +0200673 ninjaArgs := []string{
Dan Willemsen99a75cd2017-08-04 16:04:04 -0700674 "-d", "keepdepfile",
Dan Willemsen08218222020-05-18 14:02:02 -0700675 "-d", "stats",
Dan Willemsen6587bed2020-04-18 20:25:59 -0700676 "-o", "usesphonyoutputs=yes",
677 "-o", "preremoveoutputs=yes",
Dan Willemsen99a75cd2017-08-04 16:04:04 -0700678 "-w", "dupbuild=err",
Dan Willemsen6587bed2020-04-18 20:25:59 -0700679 "-w", "outputdir=err",
680 "-w", "missingoutfile=err",
Dan Willemsen99a75cd2017-08-04 16:04:04 -0700681 "-j", strconv.Itoa(config.Parallel()),
Dan Willemsen02736672018-07-17 17:54:31 -0700682 "--frontend_file", fifo,
usta49012ee2023-05-22 16:33:27 -0400683 "-f", filepath.Join(config.SoongOutDir(), "bootstrap.ninja"),
Lukacs T. Berki56ebaf32021-08-12 14:03:55 +0200684 }
685
Usta Shrestha8dc8b0a2022-08-10 17:39:37 -0400686 if extra, ok := config.Environment().Get("SOONG_UI_NINJA_ARGS"); ok {
687 ctx.Printf(`CAUTION: arguments in $SOONG_UI_NINJA_ARGS=%q, e.g. "-n", can make soong_build FAIL or INCORRECT`, extra)
688 ninjaArgs = append(ninjaArgs, strings.Fields(extra)...)
689 }
690
Lukacs T. Berki56ebaf32021-08-12 14:03:55 +0200691 ninjaArgs = append(ninjaArgs, targets...)
usta49012ee2023-05-22 16:33:27 -0400692 cmd := Command(ctx, config, "soong bootstrap",
Lukacs T. Berki56ebaf32021-08-12 14:03:55 +0200693 config.PrebuiltBuildTool("ninja"), ninjaArgs...)
Jingwen Chen7c6089a2020-11-02 02:56:20 -0500694
Lukacs T. Berkib14ad7b2021-03-09 10:43:57 +0100695 var ninjaEnv Environment
Lukacs T. Berki73ab9282021-03-10 10:48:39 +0100696
697 // This is currently how the command line to invoke soong_build finds the
698 // root of the source tree and the output root
Lukacs T. Berkib14ad7b2021-03-09 10:43:57 +0100699 ninjaEnv.Set("TOP", os.Getenv("TOP"))
Lukacs T. Berki7d613bf2021-03-02 10:09:41 +0100700
Lukacs T. Berkib14ad7b2021-03-09 10:43:57 +0100701 cmd.Environment = &ninjaEnv
Dan Willemsen99a75cd2017-08-04 16:04:04 -0700702 cmd.Sandbox = soongSandbox
Colin Cross7b97ecd2019-06-19 13:17:59 -0700703 cmd.RunAndStreamOrFatal()
Dan Willemsen1e704462016-08-21 15:17:17 -0700704 }
Lukacs T. Berki56ebaf32021-08-12 14:03:55 +0200705
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200706 targets := make([]string, 0, 0)
Lukacs T. Berki56ebaf32021-08-12 14:03:55 +0200707
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200708 if config.JsonModuleGraph() {
709 targets = append(targets, config.ModuleGraphFile())
Lukacs T. Berki56ebaf32021-08-12 14:03:55 +0200710 }
711
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200712 if config.Bp2Build() {
Lukacs T. Berkic541cd22022-10-26 07:26:50 +0000713 targets = append(targets, config.Bp2BuildWorkspaceMarkerFile())
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200714 }
715
Lukacs T. Berki3a821692021-09-06 17:08:02 +0200716 if config.Queryview() {
717 targets = append(targets, config.QueryviewMarkerFile())
718 }
719
Lukacs T. Berkic6012f32021-09-06 18:31:46 +0200720 if config.SoongDocs() {
721 targets = append(targets, config.SoongDocsHtml())
722 }
723
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200724 if config.SoongBuildInvocationNeeded() {
725 // This build generates <builddir>/build.ninja, which is used later by build/soong/ui/build/build.go#Build().
Cole Faust65f298c2021-10-28 16:05:13 -0700726 targets = append(targets, config.SoongNinjaFile())
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200727 }
728
Colin Crossaa9a2732023-10-27 10:54:27 -0700729 beforeSoongTimestamp := time.Now()
730
usta49012ee2023-05-22 16:33:27 -0400731 ninja(targets...)
Colin Crossb72c9092020-02-10 11:23:49 -0800732
Colin Crossaa9a2732023-10-27 10:54:27 -0700733 loadSoongBuildMetrics(ctx, config, beforeSoongTimestamp)
734
Colin Cross8ba7d472020-06-25 11:27:52 -0700735 distGzipFile(ctx, config, config.SoongNinjaFile(), "soong")
Jihoon Kang9f4f8a32022-08-16 00:57:30 +0000736 distFile(ctx, config, config.SoongVarsFile(), "soong")
Colin Cross8ba7d472020-06-25 11:27:52 -0700737
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000738 if !config.SkipKati() {
Colin Cross8ba7d472020-06-25 11:27:52 -0700739 distGzipFile(ctx, config, config.SoongAndroidMk(), "soong")
740 distGzipFile(ctx, config, config.SoongMakeVarsMk(), "soong")
741 }
742
Rob Seymour33cd10d2022-03-02 23:10:25 +0000743 if config.JsonModuleGraph() {
744 distGzipFile(ctx, config, config.ModuleGraphFile(), "soong")
745 }
Colin Crossb72c9092020-02-10 11:23:49 -0800746}
747
Colin Crossaa9a2732023-10-27 10:54:27 -0700748// loadSoongBuildMetrics reads out/soong_build_metrics.pb if it was generated by soong_build and copies the
749// events stored in it into the soong_ui trace to provide introspection into how long the different phases of
750// soong_build are taking.
751func loadSoongBuildMetrics(ctx Context, config Config, oldTimestamp time.Time) {
752 soongBuildMetricsFile := config.SoongBuildMetrics()
753 if metricsStat, err := os.Stat(soongBuildMetricsFile); err != nil {
754 ctx.Verbosef("Failed to stat %s: %s", soongBuildMetricsFile, err)
755 return
756 } else if !metricsStat.ModTime().After(oldTimestamp) {
757 ctx.Verbosef("%s timestamp not later after running soong, expected %s > %s",
758 soongBuildMetricsFile, metricsStat.ModTime(), oldTimestamp)
759 return
760 }
761
Colin Crossb67b0612023-10-31 10:02:45 -0700762 metricsData, err := os.ReadFile(soongBuildMetricsFile)
Colin Crossaa9a2732023-10-27 10:54:27 -0700763 if err != nil {
764 ctx.Verbosef("Failed to read %s: %s", soongBuildMetricsFile, err)
765 return
766 }
767
768 soongBuildMetrics := metrics_proto.SoongBuildMetrics{}
769 err = proto.Unmarshal(metricsData, &soongBuildMetrics)
770 if err != nil {
771 ctx.Verbosef("Failed to unmarshal %s: %s", soongBuildMetricsFile, err)
772 return
773 }
774 for _, event := range soongBuildMetrics.Events {
775 desc := event.GetDescription()
776 if dot := strings.LastIndexByte(desc, '.'); dot >= 0 {
777 desc = desc[dot+1:]
778 }
779 ctx.Tracer.Complete(desc, ctx.Thread,
780 event.GetStartTime(), event.GetStartTime()+event.GetRealTime())
781 }
Colin Cross46b0c752023-10-27 14:56:12 -0700782 for _, event := range soongBuildMetrics.PerfCounters {
783 timestamp := event.GetTime()
784 for _, group := range event.Groups {
785 counters := make([]tracer.Counter, 0, len(group.Counters))
786 for _, counter := range group.Counters {
787 counters = append(counters, tracer.Counter{
788 Name: counter.GetName(),
789 Value: counter.GetValue(),
790 })
791 }
792 ctx.Tracer.CountersAtTime(group.GetName(), ctx.Thread, timestamp, counters)
793 }
794 }
Colin Crossaa9a2732023-10-27 10:54:27 -0700795}
796
Chris Parsonsb6d6fc92023-10-30 16:21:06 +0000797func cleanBazelFiles(config Config) {
798 files := []string{
799 shared.JoinPath(config.SoongOutDir(), "bp2build"),
800 shared.JoinPath(config.SoongOutDir(), "workspace"),
801 shared.JoinPath(config.SoongOutDir(), bazel.SoongInjectionDirName),
802 shared.JoinPath(config.OutDir(), "bazel")}
803
804 for _, f := range files {
805 os.RemoveAll(f)
806 }
807}
808
Lukacs T. Berki90b43342021-11-02 14:42:04 +0100809func runMicrofactory(ctx Context, config Config, name string, pkg string, mapping map[string]string) {
Sasha Smundak7ae80a72021-04-09 12:03:51 -0700810 ctx.BeginTrace(metrics.RunSoong, name)
811 defer ctx.EndTrace()
812 cfg := microfactory.Config{TrimPath: absPath(ctx, ".")}
813 for pkgPrefix, pathPrefix := range mapping {
814 cfg.Map(pkgPrefix, pathPrefix)
815 }
816
Lukacs T. Berki90b43342021-11-02 14:42:04 +0100817 exePath := filepath.Join(config.SoongOutDir(), name)
Sasha Smundak7ae80a72021-04-09 12:03:51 -0700818 dir := filepath.Dir(exePath)
819 if err := os.MkdirAll(dir, 0777); err != nil {
820 ctx.Fatalf("cannot create %s: %s", dir, err)
821 }
822 if _, err := microfactory.Build(&cfg, exePath, pkg); err != nil {
823 ctx.Fatalf("failed to build %s: %s", name, err)
824 }
825}