Enable bazel profiling in soong_build.
Bazel is executed several times during the execution of soong_build. For each bazel execution, generate a profile and save under the BAZEL_METRICS_DIR which is defined in soong_ui. Bug: b/174479924 Test: * USE_BAZEL_ANALYSIS=1 USE_BAZEL=1 m nothing and checked if the cquery and graph build bazel profiles were generated. * Verified that the generated bazel profiles were uploaded to the local dev metrics pipeline. Change-Id: I3d20204484dc6c5a1525a5d3eec1d62cfb33535b
This commit is contained in:
parent
57fab96e01
commit
05ab2d0731
7 changed files with 54 additions and 7 deletions
|
@ -26,6 +26,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"android/soong/bazel"
|
||||||
|
"android/soong/shared"
|
||||||
"github.com/google/blueprint/bootstrap"
|
"github.com/google/blueprint/bootstrap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -68,6 +70,7 @@ type bazelContext struct {
|
||||||
outputBase string
|
outputBase string
|
||||||
workspaceDir string
|
workspaceDir string
|
||||||
buildDir string
|
buildDir string
|
||||||
|
metricsDir string
|
||||||
|
|
||||||
requests map[cqueryKey]bool // cquery requests that have not yet been issued to Bazel
|
requests map[cqueryKey]bool // cquery requests that have not yet been issued to Bazel
|
||||||
requestMutex sync.Mutex // requests can be written in parallel
|
requestMutex sync.Mutex // requests can be written in parallel
|
||||||
|
@ -153,6 +156,11 @@ func NewBazelContext(c *config) (BazelContext, error) {
|
||||||
} else {
|
} else {
|
||||||
missingEnvVars = append(missingEnvVars, "BAZEL_WORKSPACE")
|
missingEnvVars = append(missingEnvVars, "BAZEL_WORKSPACE")
|
||||||
}
|
}
|
||||||
|
if len(c.Getenv("BAZEL_METRICS_DIR")) > 1 {
|
||||||
|
bazelCtx.metricsDir = c.Getenv("BAZEL_METRICS_DIR")
|
||||||
|
} else {
|
||||||
|
missingEnvVars = append(missingEnvVars, "BAZEL_METRICS_DIR")
|
||||||
|
}
|
||||||
if len(missingEnvVars) > 0 {
|
if len(missingEnvVars) > 0 {
|
||||||
return nil, errors.New(fmt.Sprintf("missing required env vars to use bazel: %s", missingEnvVars))
|
return nil, errors.New(fmt.Sprintf("missing required env vars to use bazel: %s", missingEnvVars))
|
||||||
} else {
|
} else {
|
||||||
|
@ -160,6 +168,10 @@ func NewBazelContext(c *config) (BazelContext, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (context *bazelContext) BazelMetricsDir() string {
|
||||||
|
return context.metricsDir
|
||||||
|
}
|
||||||
|
|
||||||
func (context *bazelContext) BazelEnabled() bool {
|
func (context *bazelContext) BazelEnabled() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -189,12 +201,13 @@ func pwdPrefix() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (context *bazelContext) issueBazelCommand(command string, labels []string,
|
func (context *bazelContext) issueBazelCommand(runName bazel.RunName, command string, labels []string,
|
||||||
extraFlags ...string) (string, error) {
|
extraFlags ...string) (string, error) {
|
||||||
|
|
||||||
cmdFlags := []string{"--output_base=" + context.outputBase, command}
|
cmdFlags := []string{"--output_base=" + context.outputBase, command}
|
||||||
cmdFlags = append(cmdFlags, labels...)
|
cmdFlags = append(cmdFlags, labels...)
|
||||||
cmdFlags = append(cmdFlags, "--package_path=%workspace%/"+context.intermediatesDir())
|
cmdFlags = append(cmdFlags, "--package_path=%workspace%/"+context.intermediatesDir())
|
||||||
|
cmdFlags = append(cmdFlags, "--profile="+shared.BazelMetricsFilename(context, runName))
|
||||||
cmdFlags = append(cmdFlags, extraFlags...)
|
cmdFlags = append(cmdFlags, extraFlags...)
|
||||||
|
|
||||||
bazelCmd := exec.Command(context.bazelPath, cmdFlags...)
|
bazelCmd := exec.Command(context.bazelPath, cmdFlags...)
|
||||||
|
@ -341,7 +354,7 @@ func (context *bazelContext) InvokeBazel() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
buildroot_label := "//:buildroot"
|
buildroot_label := "//:buildroot"
|
||||||
cqueryOutput, err = context.issueBazelCommand("cquery",
|
cqueryOutput, err = context.issueBazelCommand(bazel.CqueryBuildRootRunName, "cquery",
|
||||||
[]string{fmt.Sprintf("deps(%s)", buildroot_label)},
|
[]string{fmt.Sprintf("deps(%s)", buildroot_label)},
|
||||||
"--output=starlark",
|
"--output=starlark",
|
||||||
"--starlark:file="+cquery_file_relpath)
|
"--starlark:file="+cquery_file_relpath)
|
||||||
|
@ -371,7 +384,7 @@ func (context *bazelContext) InvokeBazel() error {
|
||||||
// bazel actions should either be added to the Ninja file and executed later,
|
// bazel actions should either be added to the Ninja file and executed later,
|
||||||
// or bazel should handle execution.
|
// or bazel should handle execution.
|
||||||
// TODO(cparsons): Use --target_pattern_file to avoid command line limits.
|
// TODO(cparsons): Use --target_pattern_file to avoid command line limits.
|
||||||
_, err = context.issueBazelCommand("build", []string{buildroot_label})
|
_, err = context.issueBazelCommand(bazel.BazelBuildPhonyRootRunName, "build", []string{buildroot_label})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -2,6 +2,7 @@ bootstrap_go_package {
|
||||||
name: "soong-bazel",
|
name: "soong-bazel",
|
||||||
pkgPath: "android/soong/bazel",
|
pkgPath: "android/soong/bazel",
|
||||||
srcs: [
|
srcs: [
|
||||||
|
"constants.go",
|
||||||
"properties.go",
|
"properties.go",
|
||||||
],
|
],
|
||||||
pluginFor: [
|
pluginFor: [
|
||||||
|
|
26
bazel/constants.go
Normal file
26
bazel/constants.go
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
package bazel
|
||||||
|
|
||||||
|
type RunName string
|
||||||
|
|
||||||
|
// Below is a list bazel execution run names used through out the
|
||||||
|
// Platform Build systems. Each run name represents an unique key
|
||||||
|
// to query the bazel metrics.
|
||||||
|
const (
|
||||||
|
// Perform a bazel build of the phony root to generate symlink forests
|
||||||
|
// for dependencies of the bazel build.
|
||||||
|
BazelBuildPhonyRootRunName = RunName("bazel-build-phony-root")
|
||||||
|
|
||||||
|
// Perform aquery of the bazel build root to retrieve action information.
|
||||||
|
AqueryBuildRootRunName = RunName("aquery-buildroot")
|
||||||
|
|
||||||
|
// Perform cquery of the Bazel build root and its dependencies.
|
||||||
|
CqueryBuildRootRunName = RunName("cquery-buildroot")
|
||||||
|
|
||||||
|
// Run bazel as a ninja executer
|
||||||
|
BazelNinjaExecRunName = RunName("bazel-ninja-exec")
|
||||||
|
)
|
||||||
|
|
||||||
|
// String returns the name of the run.
|
||||||
|
func (c RunName) String() string {
|
||||||
|
return string(c)
|
||||||
|
}
|
|
@ -4,4 +4,7 @@ bootstrap_go_package {
|
||||||
srcs: [
|
srcs: [
|
||||||
"paths.go",
|
"paths.go",
|
||||||
],
|
],
|
||||||
|
deps: [
|
||||||
|
"soong-bazel",
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@ package shared
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"android/soong/bazel"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A SharedPaths represents a list of paths that are shared between
|
// A SharedPaths represents a list of paths that are shared between
|
||||||
|
@ -37,6 +39,6 @@ func TempDirForOutDir(outDir string) (tempPath string) {
|
||||||
// on the action name. This is to help to store a set of bazel
|
// on the action name. This is to help to store a set of bazel
|
||||||
// profiles since bazel may execute multiple times during a single
|
// profiles since bazel may execute multiple times during a single
|
||||||
// build.
|
// build.
|
||||||
func BazelMetricsFilename(s SharedPaths, actionName string) string {
|
func BazelMetricsFilename(s SharedPaths, actionName bazel.RunName) string {
|
||||||
return filepath.Join(s.BazelMetricsDir(), actionName+"_bazel_profile.gz")
|
return filepath.Join(s.BazelMetricsDir(), actionName.String()+"_bazel_profile.gz")
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"android/soong/bazel"
|
||||||
"android/soong/shared"
|
"android/soong/shared"
|
||||||
"android/soong/ui/metrics"
|
"android/soong/ui/metrics"
|
||||||
)
|
)
|
||||||
|
@ -97,9 +98,9 @@ func runBazel(ctx Context, config Config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start constructing the `build` command.
|
// Start constructing the `build` command.
|
||||||
actionName := "build"
|
actionName := bazel.BazelNinjaExecRunName
|
||||||
cmd.Args = append(cmd.Args,
|
cmd.Args = append(cmd.Args,
|
||||||
actionName,
|
"build",
|
||||||
// Use output_groups to select the set of outputs to produce from a
|
// Use output_groups to select the set of outputs to produce from a
|
||||||
// ninja_build target.
|
// ninja_build target.
|
||||||
"--output_groups="+outputGroups,
|
"--output_groups="+outputGroups,
|
||||||
|
|
|
@ -156,6 +156,7 @@ func runSoong(ctx Context, config Config) {
|
||||||
cmd.Environment.Set("BAZEL_HOME", filepath.Join(config.BazelOutDir(), "bazelhome"))
|
cmd.Environment.Set("BAZEL_HOME", filepath.Join(config.BazelOutDir(), "bazelhome"))
|
||||||
cmd.Environment.Set("BAZEL_OUTPUT_BASE", filepath.Join(config.BazelOutDir(), "output"))
|
cmd.Environment.Set("BAZEL_OUTPUT_BASE", filepath.Join(config.BazelOutDir(), "output"))
|
||||||
cmd.Environment.Set("BAZEL_WORKSPACE", absPath(ctx, "."))
|
cmd.Environment.Set("BAZEL_WORKSPACE", absPath(ctx, "."))
|
||||||
|
cmd.Environment.Set("BAZEL_METRICS_DIR", config.BazelMetricsDir())
|
||||||
|
|
||||||
cmd.Environment.Set("SOONG_SANDBOX_SOONG_BUILD", "true")
|
cmd.Environment.Set("SOONG_SANDBOX_SOONG_BUILD", "true")
|
||||||
cmd.Sandbox = soongSandbox
|
cmd.Sandbox = soongSandbox
|
||||||
|
|
Loading…
Reference in a new issue