diff --git a/android/bazel_handler.go b/android/bazel_handler.go index b3b698eb0..e2751d6c9 100644 --- a/android/bazel_handler.go +++ b/android/bazel_handler.go @@ -150,8 +150,9 @@ type BazelContext interface { // ** end Cquery Results Retrieval Functions // Issues commands to Bazel to receive results for all cquery requests - // queued in the BazelContext. - InvokeBazel(config Config) error + // queued in the BazelContext. The ctx argument is optional and is only + // used for performance data collection + InvokeBazel(config Config, ctx *Context) error // Returns true if Bazel handling is enabled for the module with the given name. // Note that this only implies "bazel mixed build" allowlisting. The caller @@ -259,7 +260,7 @@ func (m MockBazelContext) GetCcUnstrippedInfo(label string, _ configKey) (cquery return result, nil } -func (m MockBazelContext) InvokeBazel(_ Config) error { +func (m MockBazelContext) InvokeBazel(_ Config, ctx *Context) error { panic("unimplemented") } @@ -355,7 +356,7 @@ func (n noopBazelContext) GetCcUnstrippedInfo(_ string, _ configKey) (cquery.CcU panic("implement me") } -func (n noopBazelContext) InvokeBazel(_ Config) error { +func (n noopBazelContext) InvokeBazel(_ Config, ctx *Context) error { panic("unimplemented") } @@ -865,11 +866,48 @@ func (p *bazelPaths) outDir() string { return filepath.Dir(p.soongOutDir) } +const buildrootLabel = "@soong_injection//mixed_builds:buildroot" + +var ( + cqueryCmd = bazelCommand{"cquery", fmt.Sprintf("deps(%s, 2)", buildrootLabel)} + aqueryCmd = bazelCommand{"aquery", fmt.Sprintf("deps(%s)", buildrootLabel)} + buildCmd = bazelCommand{"build", "@soong_injection//mixed_builds:phonyroot"} +) + // Issues commands to Bazel to receive results for all cquery requests // queued in the BazelContext. -func (context *bazelContext) InvokeBazel(config Config) error { - context.results = make(map[cqueryKey]string) +func (context *bazelContext) InvokeBazel(config Config, ctx *Context) error { + if ctx != nil { + ctx.EventHandler.Begin("bazel") + defer ctx.EventHandler.End("bazel") + } + if metricsDir := context.paths.BazelMetricsDir(); metricsDir != "" { + if err := os.MkdirAll(metricsDir, 0777); err != nil { + return err + } + } + context.results = make(map[cqueryKey]string) + if err := context.runCquery(ctx); err != nil { + return err + } + if err := context.runAquery(config, ctx); err != nil { + return err + } + if err := context.generateBazelSymlinks(ctx); err != nil { + return err + } + + // Clear requests. + context.requests = map[cqueryKey]bool{} + return nil +} + +func (context *bazelContext) runCquery(ctx *Context) error { + if ctx != nil { + ctx.EventHandler.Begin("cquery") + defer ctx.EventHandler.End("cquery") + } soongInjectionPath := absolutePath(context.paths.injectedFilesDir()) mixedBuildsPath := filepath.Join(soongInjectionPath, "mixed_builds") if _, err := os.Stat(mixedBuildsPath); os.IsNotExist(err) { @@ -878,13 +916,6 @@ func (context *bazelContext) InvokeBazel(config Config) error { return err } } - - if metricsDir := context.paths.BazelMetricsDir(); metricsDir != "" { - err := os.MkdirAll(metricsDir, 0777) - if err != nil { - return err - } - } if err := ioutil.WriteFile(filepath.Join(soongInjectionPath, "WORKSPACE.bazel"), []byte{}, 0666); err != nil { return err } @@ -899,8 +930,6 @@ func (context *bazelContext) InvokeBazel(config Config) error { return err } - const buildrootLabel = "@soong_injection//mixed_builds:buildroot" - cqueryCmd := bazelCommand{"cquery", fmt.Sprintf("deps(%s, 2)", buildrootLabel)} cqueryCommandWithFlag := context.createBazelCommand(context.paths, bazel.CqueryBuildRootRunName, cqueryCmd, "--output=starlark", "--starlark:file="+absolutePath(cqueryFileRelpath)) cqueryOutput, cqueryErrorMessage, cqueryErr := context.issueBazelCommand(cqueryCommandWithFlag) @@ -926,7 +955,14 @@ func (context *bazelContext) InvokeBazel(config Config) error { getCqueryId(val), cqueryOutput, cqueryErrorMessage) } } + return nil +} +func (context *bazelContext) runAquery(config Config, ctx *Context) error { + if ctx != nil { + ctx.EventHandler.Begin("aquery") + defer ctx.EventHandler.End("aquery") + } // Issue an aquery command to retrieve action information about the bazel build tree. // // Use jsonproto instead of proto; actual proto parsing would require a dependency on Bazel's @@ -951,25 +987,25 @@ func (context *bazelContext) InvokeBazel(config Config) error { extraFlags = append(extraFlags, "--instrumentation_filter="+strings.Join(paths, ",")) } } - aqueryCmd := bazelCommand{"aquery", fmt.Sprintf("deps(%s)", buildrootLabel)} - if aqueryOutput, _, err := context.issueBazelCommand(context.createBazelCommand(context.paths, bazel.AqueryBuildRootRunName, aqueryCmd, - extraFlags...)); err == nil { - context.buildStatements, context.depsets, err = bazel.AqueryBuildStatements([]byte(aqueryOutput)) - } else { + aqueryOutput, _, err := context.issueBazelCommand(context.createBazelCommand(context.paths, bazel.AqueryBuildRootRunName, aqueryCmd, + extraFlags...)) + if err != nil { return err } + context.buildStatements, context.depsets, err = bazel.AqueryBuildStatements([]byte(aqueryOutput)) + return err +} +func (context *bazelContext) generateBazelSymlinks(ctx *Context) error { + if ctx != nil { + ctx.EventHandler.Begin("symlinks") + defer ctx.EventHandler.End("symlinks") + } // Issue a build command of the phony root to generate symlink forests for dependencies of the // Bazel build. This is necessary because aquery invocations do not generate this symlink forest, // but some of symlinks may be required to resolve source dependencies of the build. - buildCmd := bazelCommand{"build", "@soong_injection//mixed_builds:phonyroot"} - if _, _, err := context.issueBazelCommand(context.createBazelCommand(context.paths, bazel.BazelBuildPhonyRootRunName, buildCmd)); err != nil { - return err - } - - // Clear requests. - context.requests = map[cqueryKey]bool{} - return nil + _, _, err := context.issueBazelCommand(context.createBazelCommand(context.paths, bazel.BazelBuildPhonyRootRunName, buildCmd)) + return err } func (context *bazelContext) BuildStatementsToRegister() []bazel.BuildStatement { diff --git a/android/bazel_handler_test.go b/android/bazel_handler_test.go index 4b8f0f69a..bc16cb53a 100644 --- a/android/bazel_handler_test.go +++ b/android/bazel_handler_test.go @@ -23,7 +23,7 @@ func TestRequestResultsAfterInvokeBazel(t *testing.T) { bazelCommand{command: "cquery", expression: "deps(@soong_injection//mixed_builds:buildroot, 2)"}: `@//foo:bar|arm64_armv8-a|android>>out/foo/bar.txt`, }) bazelContext.QueueBazelRequest(label, cquery.GetOutputFiles, cfg) - err := bazelContext.InvokeBazel(testConfig) + err := bazelContext.InvokeBazel(testConfig, nil) if err != nil { t.Fatalf("Did not expect error invoking Bazel, but got %s", err) } @@ -37,7 +37,7 @@ func TestRequestResultsAfterInvokeBazel(t *testing.T) { func TestInvokeBazelWritesBazelFiles(t *testing.T) { bazelContext, baseDir := testBazelContext(t, map[bazelCommand]string{}) - err := bazelContext.InvokeBazel(testConfig) + err := bazelContext.InvokeBazel(testConfig, nil) if err != nil { t.Fatalf("Did not expect error invoking Bazel, but got %s", err) } @@ -118,7 +118,7 @@ func TestInvokeBazelPopulatesBuildStatements(t *testing.T) { bazelContext, _ := testBazelContext(t, map[bazelCommand]string{ bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}: string(data)}) - err = bazelContext.InvokeBazel(testConfig) + err = bazelContext.InvokeBazel(testConfig, nil) if err != nil { t.Fatalf("testCase #%d: did not expect error invoking Bazel, but got %s", i+1, err) } @@ -170,7 +170,7 @@ func TestCoverageFlagsAfterInvokeBazel(t *testing.T) { func verifyExtraFlags(t *testing.T, config Config, expected string) string { bazelContext, _ := testBazelContext(t, map[bazelCommand]string{}) - err := bazelContext.InvokeBazel(config) + err := bazelContext.InvokeBazel(config, nil) if err != nil { t.Fatalf("Did not expect error invoking Bazel, but got %s", err) } @@ -197,7 +197,7 @@ func testBazelContext(t *testing.T, bazelCommandResults map[bazelCommand]string) } aqueryCommand := bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"} if _, exists := bazelCommandResults[aqueryCommand]; !exists { - bazelCommandResults[aqueryCommand] = "{}\n" + bazelCommandResults[aqueryCommand] = "" } runner := &mockBazelRunner{bazelCommandResults: bazelCommandResults} return &bazelContext{ diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go index 51d23457d..bc2d5cb07 100644 --- a/cmd/soong_build/main.go +++ b/cmd/soong_build/main.go @@ -157,9 +157,7 @@ func runMixedModeBuild(configuration android.Config, ctx *android.Context, extra defer ctx.EventHandler.End("mixed_build") bazelHook := func() error { - ctx.EventHandler.Begin("bazel") - defer ctx.EventHandler.End("bazel") - return configuration.BazelContext.InvokeBazel(configuration) + return configuration.BazelContext.InvokeBazel(configuration, ctx) } ctx.SetBeforePrepareBuildActionsHook(bazelHook) ninjaDeps := bootstrap.RunBlueprint(cmdlineArgs, bootstrap.DoEverything, ctx.Context, configuration)