Snap for 6948038 from 81788fb46daf729ae89ac357528a803ae965dcee to rvc-platform-release
Change-Id: Id72e5e614fc2b43e3995b3cb7ffce7affbfca008
diff --git a/android/androidmk.go b/android/androidmk.go
index f86061a..54a0c64 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -126,6 +126,26 @@
}
}
+func (a *AndroidMkEntries) SetPaths(name string, paths Paths) {
+ if _, ok := a.EntryMap[name]; !ok {
+ a.entryOrder = append(a.entryOrder, name)
+ }
+ a.EntryMap[name] = paths.Strings()
+}
+
+func (a *AndroidMkEntries) SetOptionalPaths(name string, paths Paths) {
+ if len(paths) > 0 {
+ a.SetPaths(name, paths)
+ }
+}
+
+func (a *AndroidMkEntries) AddPaths(name string, paths Paths) {
+ if _, ok := a.EntryMap[name]; !ok {
+ a.entryOrder = append(a.entryOrder, name)
+ }
+ a.EntryMap[name] = append(a.EntryMap[name], paths.Strings()...)
+}
+
func (a *AndroidMkEntries) SetBoolIfTrue(name string, flag bool) {
if flag {
if _, ok := a.EntryMap[name]; !ok {
diff --git a/android/arch.go b/android/arch.go
index d14221f..18ff13e 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -1440,20 +1440,15 @@
// key: value,
// },
// },
- // TODO(ccross): is this still necessary with native bridge?
if os.Class == Device {
- if (arch.ArchType == X86 && (hasArmAbi(arch) ||
- hasArmAndroidArch(ctx.Config().Targets[Android]))) ||
- (arch.ArchType == Arm &&
- hasX86AndroidArch(ctx.Config().Targets[Android])) {
+ if arch.ArchType == X86 && (hasArmAbi(arch) ||
+ hasArmAndroidArch(ctx.Config().Targets[Android])) {
field := "Arm_on_x86"
prefix := "target.arm_on_x86"
m.appendProperties(ctx, genProps, targetProp, field, prefix)
}
- if (arch.ArchType == X86_64 && (hasArmAbi(arch) ||
- hasArmAndroidArch(ctx.Config().Targets[Android]))) ||
- (arch.ArchType == Arm &&
- hasX8664AndroidArch(ctx.Config().Targets[Android])) {
+ if arch.ArchType == X86_64 && (hasArmAbi(arch) ||
+ hasArmAndroidArch(ctx.Config().Targets[Android])) {
field := "Arm_on_x86_64"
prefix := "target.arm_on_x86_64"
m.appendProperties(ctx, genProps, targetProp, field, prefix)
@@ -1600,27 +1595,7 @@
// hasArmArch returns true if targets has at least non-native_bridge arm Android arch
func hasArmAndroidArch(targets []Target) bool {
for _, target := range targets {
- if target.Os == Android && target.Arch.ArchType == Arm && target.NativeBridge == NativeBridgeDisabled {
- return true
- }
- }
- return false
-}
-
-// hasX86Arch returns true if targets has at least x86 Android arch
-func hasX86AndroidArch(targets []Target) bool {
- for _, target := range targets {
- if target.Os == Android && target.Arch.ArchType == X86 {
- return true
- }
- }
- return false
-}
-
-// hasX8664Arch returns true if targets has at least x86_64 Android arch
-func hasX8664AndroidArch(targets []Target) bool {
- for _, target := range targets {
- if target.Os == Android && target.Arch.ArchType == X86_64 {
+ if target.Os == Android && target.Arch.ArchType == Arm {
return true
}
}
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 5879e56..e4cdef0 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -333,6 +333,10 @@
if apexType == imageApex {
fmt.Fprintln(w, "ALL_MODULES.$(LOCAL_MODULE).BUNDLE :=", a.bundleModuleFile.String())
}
+ if len(a.lintReports) > 0 {
+ fmt.Fprintln(w, "ALL_MODULES.$(my_register_name).LINT_REPORTS :=",
+ strings.Join(a.lintReports.Strings(), " "))
+ }
if a.installedFilesFile != nil {
goal := "checkbuild"
diff --git a/apex/apex.go b/apex/apex.go
index b4fae34..7da8e1c 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1265,6 +1265,7 @@
hostRequiredModuleNames []string
jacocoReportClassesFile android.Path // only for javalibs and apps
+ lintDepSets java.LintDepSets // only for javalibs and apps
certificate java.Certificate // only for apps
overriddenPackageName string // only for apps
}
@@ -1387,6 +1388,9 @@
// Struct holding the merged notice file paths in different formats
mergedNotices android.NoticeOutputs
+
+ // Optional list of lint report zip files for apexes that contain java or app modules
+ lintReports android.Paths
}
func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext,
@@ -1749,9 +1753,16 @@
type javaDependency interface {
DexJar() android.Path
JacocoReportClassesFile() android.Path
+ LintDepSets() java.LintDepSets
+
Stem() string
}
+var _ javaDependency = (*java.Library)(nil)
+var _ javaDependency = (*java.SdkLibrary)(nil)
+var _ javaDependency = (*java.DexImport)(nil)
+var _ javaDependency = (*java.SdkLibraryImport)(nil)
+
func apexFileForJavaLibrary(ctx android.BaseModuleContext, lib javaDependency, module android.Module) apexFile {
dirInApex := "javalib"
fileToCopy := lib.DexJar()
@@ -1759,6 +1770,7 @@
name := strings.TrimPrefix(module.Name(), "prebuilt_")
af := newApexFile(ctx, fileToCopy, name, dirInApex, javaSharedLib, module)
af.jacocoReportClassesFile = lib.JacocoReportClassesFile()
+ af.lintDepSets = lib.LintDepSets()
af.stem = lib.Stem() + ".jar"
return af
}
@@ -2274,6 +2286,8 @@
a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx)
a.buildApexDependencyInfo(ctx)
+
+ a.buildLintReports(ctx)
}
// Enforce that Java deps of the apex are using stable SDKs to compile
diff --git a/apex/builder.go b/apex/builder.go
index 9da6ef8..8573dc0 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -752,3 +752,12 @@
},
})
}
+
+func (a *apexBundle) buildLintReports(ctx android.ModuleContext) {
+ depSetsBuilder := java.NewLintDepSetBuilder()
+ for _, fi := range a.filesInfo {
+ depSetsBuilder.Transitive(fi.lintDepSets)
+ }
+
+ a.lintReports = java.BuildModuleLintReportZips(ctx, depSetsBuilder.Build())
+}
diff --git a/cc/builder.go b/cc/builder.go
index 37fbf4e..5deb129 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -76,12 +76,12 @@
&remoteexec.REParams{
Labels: map[string]string{"type": "link", "tool": "clang"},
ExecStrategy: "${config.RECXXLinksExecStrategy}",
- Inputs: []string{"${out}.rsp"},
+ Inputs: []string{"${out}.rsp", "$implicitInputs"},
RSPFile: "${out}.rsp",
OutputFiles: []string{"${out}", "$implicitOutputs"},
ToolchainInputs: []string{"$ldCmd"},
Platform: map[string]string{remoteexec.PoolKey: "${config.RECXXLinksPool}"},
- }, []string{"ldCmd", "crtBegin", "libFlags", "crtEnd", "ldFlags", "extraLibFlags"}, []string{"implicitOutputs"})
+ }, []string{"ldCmd", "crtBegin", "libFlags", "crtEnd", "ldFlags", "extraLibFlags"}, []string{"implicitInputs", "implicitOutputs"})
partialLd, partialLdRE = remoteexec.StaticRules(pctx, "partialLd",
blueprint.RuleParams{
@@ -92,11 +92,11 @@
}, &remoteexec.REParams{
Labels: map[string]string{"type": "link", "tool": "clang"},
ExecStrategy: "${config.RECXXLinksExecStrategy}",
- Inputs: []string{"$inCommaList"},
+ Inputs: []string{"$inCommaList", "$implicitInputs"},
OutputFiles: []string{"${out}", "$implicitOutputs"},
ToolchainInputs: []string{"$ldCmd"},
Platform: map[string]string{remoteexec.PoolKey: "${config.RECXXLinksPool}"},
- }, []string{"ldCmd", "ldFlags"}, []string{"inCommaList", "implicitOutputs"})
+ }, []string{"ldCmd", "ldFlags"}, []string{"implicitInputs", "inCommaList", "implicitOutputs"})
ar = pctx.AndroidStaticRule("ar",
blueprint.RuleParams{
@@ -215,15 +215,23 @@
}, []string{"cFlags", "exportDirs"}, nil)
_ = pctx.SourcePathVariable("sAbiLinker", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-linker")
+ _ = pctx.SourcePathVariable("sAbiLinkerLibs", "prebuilts/clang-tools/${config.HostPrebuiltTag}/lib64")
- sAbiLink = pctx.AndroidStaticRule("sAbiLink",
+ sAbiLink, sAbiLinkRE = remoteexec.StaticRules(pctx, "sAbiLink",
blueprint.RuleParams{
- Command: "$sAbiLinker -o ${out} $symbolFilter -arch $arch $exportedHeaderFlags @${out}.rsp ",
+ Command: "$reTemplate$sAbiLinker -o ${out} $symbolFilter -arch $arch $exportedHeaderFlags @${out}.rsp ",
CommandDeps: []string{"$sAbiLinker"},
Rspfile: "${out}.rsp",
RspfileContent: "${in}",
- },
- "symbolFilter", "arch", "exportedHeaderFlags")
+ }, &remoteexec.REParams{
+ Labels: map[string]string{"type": "tool", "name": "abi-linker"},
+ ExecStrategy: "${config.REAbiLinkerExecStrategy}",
+ Inputs: []string{"$sAbiLinkerLibs", "${out}.rsp", "$implicitInputs"},
+ RSPFile: "${out}.rsp",
+ OutputFiles: []string{"$out"},
+ ToolchainInputs: []string{"$sAbiLinker"},
+ Platform: map[string]string{remoteexec.PoolKey: "${config.RECXXPool}"},
+ }, []string{"symbolFilter", "arch", "exportedHeaderFlags"}, []string{"implicitInputs"})
_ = pctx.SourcePathVariable("sAbiDiffer", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-diff")
@@ -695,6 +703,7 @@
if ctx.Config().IsEnvTrue("RBE_CXX_LINKS") {
rule = ldRE
args["implicitOutputs"] = strings.Join(implicitOutputs.Strings(), ",")
+ args["implicitInputs"] = strings.Join(deps.Strings(), ",")
}
ctx.Build(pctx, android.BuildParams{
@@ -729,17 +738,30 @@
for _, tag := range excludedSymbolTags {
symbolFilterStr += " --exclude-symbol-tag " + tag
}
+ rule := sAbiLink
+ args := map[string]string{
+ "symbolFilter": symbolFilterStr,
+ "arch": ctx.Arch().ArchType.Name,
+ "exportedHeaderFlags": exportedHeaderFlags,
+ }
+ if ctx.Config().IsEnvTrue("RBE_ABI_LINKER") {
+ rule = sAbiLinkRE
+ rbeImplicits := implicits.Strings()
+ for _, p := range strings.Split(exportedHeaderFlags, " ") {
+ if len(p) > 2 {
+ // Exclude the -I prefix.
+ rbeImplicits = append(rbeImplicits, p[2:])
+ }
+ }
+ args["implicitInputs"] = strings.Join(rbeImplicits, ",")
+ }
ctx.Build(pctx, android.BuildParams{
- Rule: sAbiLink,
+ Rule: rule,
Description: "header-abi-linker " + outputFile.Base(),
Output: outputFile,
Inputs: sAbiDumps,
Implicits: implicits,
- Args: map[string]string{
- "symbolFilter": symbolFilterStr,
- "arch": ctx.Arch().ArchType.Name,
- "exportedHeaderFlags": exportedHeaderFlags,
- },
+ Args: args,
})
return android.OptionalPathForPath(outputFile)
}
@@ -839,6 +861,7 @@
if ctx.Config().IsEnvTrue("RBE_CXX_LINKS") {
rule = partialLdRE
args["inCommaList"] = strings.Join(objFiles.Strings(), ",")
+ args["implicitInputs"] = strings.Join(deps.Strings(), ",")
}
ctx.Build(pctx, android.BuildParams{
Rule: rule,
diff --git a/cc/compiler.go b/cc/compiler.go
index 08ce133..f6c3587 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -333,6 +333,10 @@
}
}
+ if ctx.Target().NativeBridge == android.NativeBridgeEnabled {
+ flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_NATIVE_BRIDGE__")
+ }
+
instructionSet := String(compiler.Properties.Instruction_set)
if flags.RequiredInstructionSet != "" {
instructionSet = flags.RequiredInstructionSet
diff --git a/cc/config/global.go b/cc/config/global.go
index fce0306..57d8db9 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -261,6 +261,7 @@
pctx.VariableFunc("RECXXLinksPool", remoteexec.EnvOverrideFunc("RBE_CXX_LINKS_POOL", remoteexec.DefaultPool))
pctx.VariableFunc("RECXXLinksExecStrategy", remoteexec.EnvOverrideFunc("RBE_CXX_LINKS_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
pctx.VariableFunc("REAbiDumperExecStrategy", remoteexec.EnvOverrideFunc("RBE_ABI_DUMPER_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
+ pctx.VariableFunc("REAbiLinkerExecStrategy", remoteexec.EnvOverrideFunc("RBE_ABI_LINKER_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
}
var HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS)
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index db61fba..78e636c 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -117,6 +117,8 @@
// Command is the type of soong_ui execution. Only one type of
// execution is specified. The args are specific to the command.
func main() {
+ buildStarted := time.Now()
+
c, args := getCommand(os.Args)
if c == nil {
fmt.Fprintf(os.Stderr, "The `soong` native UI is not yet available.\n")
@@ -136,6 +138,7 @@
defer trace.Close()
met := metrics.New()
+ met.SetBuildDateTime(buildStarted)
stat := &status.Status{}
defer stat.Finish()
@@ -166,19 +169,25 @@
logsDir = filepath.Join(config.DistDir(), "logs")
}
+ buildErrorFile := filepath.Join(logsDir, c.logsPrefix+"build_error")
+ rbeMetricsFile := filepath.Join(logsDir, c.logsPrefix+"rbe_metrics.pb")
+ soongMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_metrics")
+ defer build.UploadMetrics(buildCtx, config, c.forceDumbOutput, buildStarted, buildErrorFile, rbeMetricsFile, soongMetricsFile)
+
os.MkdirAll(logsDir, 0777)
log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log"))
trace.SetOutput(filepath.Join(logsDir, c.logsPrefix+"build.trace"))
stat.AddOutput(status.NewVerboseLog(log, filepath.Join(logsDir, c.logsPrefix+"verbose.log")))
stat.AddOutput(status.NewErrorLog(log, filepath.Join(logsDir, c.logsPrefix+"error.log")))
- stat.AddOutput(status.NewProtoErrorLog(log, filepath.Join(logsDir, c.logsPrefix+"build_error")))
+ stat.AddOutput(status.NewProtoErrorLog(log, buildErrorFile))
stat.AddOutput(status.NewCriticalPath(log))
buildCtx.Verbosef("Detected %.3v GB total RAM", float32(config.TotalRAM())/(1024*1024*1024))
buildCtx.Verbosef("Parallelism (local/remote/highmem): %v/%v/%v",
config.Parallel(), config.RemoteParallel(), config.HighmemParallel())
- defer met.Dump(filepath.Join(logsDir, c.logsPrefix+"soong_metrics"))
+ defer met.Dump(soongMetricsFile)
+ defer build.DumpRBEMetrics(buildCtx, config, rbeMetricsFile)
if start, ok := os.LookupEnv("TRACE_BEGIN_SOONG"); ok {
if !strings.HasSuffix(start, "N") {
diff --git a/java/androidmk.go b/java/androidmk.go
index 62f9706..ae257d7 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -132,9 +132,7 @@
}
entries.SetString("LOCAL_MODULE_STEM", library.Stem())
- entries.AddOptionalPath("LOCAL_SOONG_LINT_REPORTS", library.linter.outputs.transitiveHTMLZip)
- entries.AddOptionalPath("LOCAL_SOONG_LINT_REPORTS", library.linter.outputs.transitiveTextZip)
- entries.AddOptionalPath("LOCAL_SOONG_LINT_REPORTS", library.linter.outputs.transitiveXMLZip)
+ entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", library.linter.reports)
},
},
}
@@ -394,9 +392,7 @@
entries.AddStrings("LOCAL_SOONG_BUILT_INSTALLED", extra.String()+":"+install)
}
- entries.AddOptionalPath("LOCAL_SOONG_LINT_REPORTS", app.linter.outputs.transitiveHTMLZip)
- entries.AddOptionalPath("LOCAL_SOONG_LINT_REPORTS", app.linter.outputs.transitiveTextZip)
- entries.AddOptionalPath("LOCAL_SOONG_LINT_REPORTS", app.linter.outputs.transitiveXMLZip)
+ entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", app.linter.reports)
},
},
ExtraFooters: []android.AndroidMkExtraFootersFunc{
diff --git a/java/config/config.go b/java/config/config.go
index 95add01..1d0dd61 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -148,9 +148,9 @@
pctx.HostBinToolVariable("DexpreoptGen", "dexpreopt_gen")
pctx.VariableFunc("REJavaPool", remoteexec.EnvOverrideFunc("RBE_JAVA_POOL", "java16"))
- pctx.VariableFunc("REJavacExecStrategy", remoteexec.EnvOverrideFunc("RBE_JAVAC_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
- pctx.VariableFunc("RED8ExecStrategy", remoteexec.EnvOverrideFunc("RBE_D8_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
- pctx.VariableFunc("RER8ExecStrategy", remoteexec.EnvOverrideFunc("RBE_R8_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
+ pctx.VariableFunc("REJavacExecStrategy", remoteexec.EnvOverrideFunc("RBE_JAVAC_EXEC_STRATEGY", remoteexec.RemoteLocalFallbackExecStrategy))
+ pctx.VariableFunc("RED8ExecStrategy", remoteexec.EnvOverrideFunc("RBE_D8_EXEC_STRATEGY", remoteexec.RemoteLocalFallbackExecStrategy))
+ pctx.VariableFunc("RER8ExecStrategy", remoteexec.EnvOverrideFunc("RBE_R8_EXEC_STRATEGY", remoteexec.RemoteLocalFallbackExecStrategy))
pctx.VariableFunc("RETurbineExecStrategy", remoteexec.EnvOverrideFunc("RBE_TURBINE_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
pctx.VariableFunc("RESignApkExecStrategy", remoteexec.EnvOverrideFunc("RBE_SIGNAPK_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
pctx.VariableFunc("REJarExecStrategy", remoteexec.EnvOverrideFunc("RBE_JAR_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 230b1f0..b564fea 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -287,6 +287,9 @@
// the dirs which Metalava extracts API levels annotations from.
Api_levels_annotations_dirs []string
+ // the filename which Metalava extracts API levels annotations from. Defaults to android.jar.
+ Api_levels_jar_filename *string
+
// if set to true, collect the values used by the Dev tools and
// write them in files packaged with the SDK. Defaults to false.
Write_sdk_values *bool
@@ -1387,34 +1390,37 @@
}
func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
- if Bool(d.properties.Api_levels_annotations_enabled) {
- d.apiVersionsXml = android.PathForModuleOut(ctx, "api-versions.xml")
-
- if len(d.properties.Api_levels_annotations_dirs) == 0 {
- ctx.PropertyErrorf("api_levels_annotations_dirs",
- "has to be non-empty if api levels annotations was enabled!")
- }
-
- cmd.FlagWithOutput("--generate-api-levels ", d.apiVersionsXml)
- cmd.FlagWithInput("--apply-api-levels ", d.apiVersionsXml)
- cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion())
- cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
-
- ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
- if t, ok := m.(*ExportedDroiddocDir); ok {
- for _, dep := range t.deps {
- if strings.HasSuffix(dep.String(), "android.jar") {
- cmd.Implicit(dep)
- }
- }
- cmd.FlagWithArg("--android-jar-pattern ", t.dir.String()+"/%/public/android.jar")
- } else {
- ctx.PropertyErrorf("api_levels_annotations_dirs",
- "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m))
- }
- })
-
+ if !Bool(d.properties.Api_levels_annotations_enabled) {
+ return
}
+
+ d.apiVersionsXml = android.PathForModuleOut(ctx, "api-versions.xml")
+
+ if len(d.properties.Api_levels_annotations_dirs) == 0 {
+ ctx.PropertyErrorf("api_levels_annotations_dirs",
+ "has to be non-empty if api levels annotations was enabled!")
+ }
+
+ cmd.FlagWithOutput("--generate-api-levels ", d.apiVersionsXml)
+ cmd.FlagWithInput("--apply-api-levels ", d.apiVersionsXml)
+ cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion())
+ cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
+
+ filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
+
+ ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
+ if t, ok := m.(*ExportedDroiddocDir); ok {
+ for _, dep := range t.deps {
+ if strings.HasSuffix(dep.String(), filename) {
+ cmd.Implicit(dep)
+ }
+ }
+ cmd.FlagWithArg("--android-jar-pattern ", t.dir.String()+"/%/public/"+filename)
+ } else {
+ ctx.PropertyErrorf("api_levels_annotations_dirs",
+ "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m))
+ }
+ })
}
func (d *Droidstubs) apiToXmlFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
diff --git a/java/java.go b/java/java.go
index 0a764e6..4612b76 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1683,6 +1683,9 @@
j.linter.compileSdkVersion = lintSDKVersionString(j.sdkVersion())
j.linter.javaLanguageLevel = flags.javaVersion.String()
j.linter.kotlinLanguageLevel = "1.3"
+ if j.ApexName() != "" && ctx.Config().UnbundledBuild() {
+ j.linter.buildModuleReportZip = true
+ }
j.linter.lint(ctx)
}
@@ -2738,6 +2741,10 @@
return nil
}
+func (a *DexImport) LintDepSets() LintDepSets {
+ return LintDepSets{}
+}
+
func (j *DexImport) IsInstallable() bool {
return true
}
diff --git a/java/java_test.go b/java/java_test.go
index f0de52f..8797119 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1006,6 +1006,62 @@
}
}
+func TestDroidstubs(t *testing.T) {
+ ctx, _ := testJavaWithFS(t, `
+ droiddoc_exported_dir {
+ name: "droiddoc-templates-sdk",
+ path: ".",
+ }
+
+ droidstubs {
+ name: "bar-stubs",
+ srcs: [
+ "bar-doc/a.java",
+ ],
+ api_levels_annotations_dirs: [
+ "droiddoc-templates-sdk",
+ ],
+ api_levels_annotations_enabled: true,
+ }
+
+ droidstubs {
+ name: "bar-stubs-other",
+ srcs: [
+ "bar-doc/a.java",
+ ],
+ api_levels_annotations_dirs: [
+ "droiddoc-templates-sdk",
+ ],
+ api_levels_annotations_enabled: true,
+ api_levels_jar_filename: "android.other.jar",
+ }
+ `,
+ map[string][]byte{
+ "bar-doc/a.java": nil,
+ })
+ testcases := []struct {
+ moduleName string
+ expectedJarFilename string
+ }{
+ {
+ moduleName: "bar-stubs",
+ expectedJarFilename: "android.jar",
+ },
+ {
+ moduleName: "bar-stubs-other",
+ expectedJarFilename: "android.other.jar",
+ },
+ }
+ for _, c := range testcases {
+ m := ctx.ModuleForTests(c.moduleName, "android_common")
+ metalava := m.Rule("metalava")
+ expected := "--android-jar-pattern ./%/public/" + c.expectedJarFilename
+ if actual := metalava.RuleParams.Command; !strings.Contains(actual, expected) {
+ t.Errorf("For %q, expected metalava argument %q, but was not found %q", c.moduleName, expected, actual)
+ }
+ }
+}
+
func TestDroidstubsWithSystemModules(t *testing.T) {
ctx, _ := testJava(t, `
droidstubs {
diff --git a/java/lint.go b/java/lint.go
index 20a7dc4..6391067 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -17,6 +17,7 @@
import (
"fmt"
"sort"
+ "strings"
"android/soong/android"
)
@@ -68,28 +69,78 @@
outputs lintOutputs
properties LintProperties
+ reports android.Paths
+
buildModuleReportZip bool
}
type lintOutputs struct {
- html android.ModuleOutPath
- text android.ModuleOutPath
- xml android.ModuleOutPath
+ html android.Path
+ text android.Path
+ xml android.Path
- transitiveHTML *android.DepSet
- transitiveText *android.DepSet
- transitiveXML *android.DepSet
-
- transitiveHTMLZip android.OptionalPath
- transitiveTextZip android.OptionalPath
- transitiveXMLZip android.OptionalPath
+ depSets LintDepSets
}
-type lintOutputIntf interface {
+type lintOutputsIntf interface {
lintOutputs() *lintOutputs
}
-var _ lintOutputIntf = (*linter)(nil)
+type lintDepSetsIntf interface {
+ LintDepSets() LintDepSets
+}
+
+type LintDepSets struct {
+ HTML, Text, XML *android.DepSet
+}
+
+type LintDepSetsBuilder struct {
+ HTML, Text, XML *android.DepSetBuilder
+}
+
+func NewLintDepSetBuilder() LintDepSetsBuilder {
+ return LintDepSetsBuilder{
+ HTML: android.NewDepSetBuilder(android.POSTORDER),
+ Text: android.NewDepSetBuilder(android.POSTORDER),
+ XML: android.NewDepSetBuilder(android.POSTORDER),
+ }
+}
+
+func (l LintDepSetsBuilder) Direct(html, text, xml android.Path) LintDepSetsBuilder {
+ l.HTML.Direct(html)
+ l.Text.Direct(text)
+ l.XML.Direct(xml)
+ return l
+}
+
+func (l LintDepSetsBuilder) Transitive(depSets LintDepSets) LintDepSetsBuilder {
+ if depSets.HTML != nil {
+ l.HTML.Transitive(depSets.HTML)
+ }
+ if depSets.Text != nil {
+ l.Text.Transitive(depSets.Text)
+ }
+ if depSets.XML != nil {
+ l.XML.Transitive(depSets.XML)
+ }
+ return l
+}
+
+func (l LintDepSetsBuilder) Build() LintDepSets {
+ return LintDepSets{
+ HTML: l.HTML.Build(),
+ Text: l.Text.Build(),
+ XML: l.XML.Build(),
+ }
+}
+
+func (l *linter) LintDepSets() LintDepSets {
+ return l.outputs.depSets
+}
+
+var _ lintDepSetsIntf = (*linter)(nil)
+
+var _ lintOutputsIntf = (*linter)(nil)
func (l *linter) lintOutputs() *lintOutputs {
return &l.outputs
@@ -104,7 +155,16 @@
return
}
- ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), extraLintCheckTag, l.properties.Lint.Extra_check_modules...)
+ extraCheckModules := l.properties.Lint.Extra_check_modules
+
+ if checkOnly := ctx.Config().Getenv("ANDROID_LINT_CHECK"); checkOnly != "" {
+ if checkOnlyModules := ctx.Config().Getenv("ANDROID_LINT_CHECK_EXTRA_MODULES"); checkOnlyModules != "" {
+ extraCheckModules = strings.Split(checkOnlyModules, ",")
+ }
+ }
+
+ ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(),
+ extraLintCheckTag, extraCheckModules...)
}
func (l *linter) writeLintProjectXML(ctx android.ModuleContext,
@@ -237,16 +297,11 @@
text := android.PathForModuleOut(ctx, "lint-report.txt")
xml := android.PathForModuleOut(ctx, "lint-report.xml")
- htmlDeps := android.NewDepSetBuilder(android.POSTORDER).Direct(html)
- textDeps := android.NewDepSetBuilder(android.POSTORDER).Direct(text)
- xmlDeps := android.NewDepSetBuilder(android.POSTORDER).Direct(xml)
+ depSetsBuilder := NewLintDepSetBuilder().Direct(html, text, xml)
ctx.VisitDirectDepsWithTag(staticLibTag, func(dep android.Module) {
- if depLint, ok := dep.(lintOutputIntf); ok {
- depLintOutputs := depLint.lintOutputs()
- htmlDeps.Transitive(depLintOutputs.transitiveHTML)
- textDeps.Transitive(depLintOutputs.transitiveText)
- xmlDeps.Transitive(depLintOutputs.transitiveXML)
+ if depLint, ok := dep.(lintDepSetsIntf); ok {
+ depSetsBuilder.Transitive(depLint.LintDepSets())
}
})
@@ -262,7 +317,7 @@
apiVersionsXMLPath = copiedAPIVersionsXmlPath(ctx)
}
- rule.Command().
+ cmd := rule.Command().
Text("(").
Flag("JAVA_OPTS=-Xmx2048m").
FlagWithArg("ANDROID_SDK_HOME=", homeDir.String()).
@@ -282,9 +337,13 @@
FlagWithArg("--url ", fmt.Sprintf(".=.,%s=out", android.PathForOutput(ctx).String())).
Flag("--exitcode").
Flags(l.properties.Lint.Flags).
- Implicits(deps).
- Text("|| (").Text("cat").Input(text).Text("; exit 7)").
- Text(")")
+ Implicits(deps)
+
+ if checkOnly := ctx.Config().Getenv("ANDROID_LINT_CHECK"); checkOnly != "" {
+ cmd.FlagWithArg("--check ", checkOnly)
+ }
+
+ cmd.Text("|| (").Text("cat").Input(text).Text("; exit 7)").Text(")")
rule.Command().Text("rm -rf").Flag(cacheDir.String()).Flag(homeDir.String())
@@ -295,26 +354,35 @@
text: text,
xml: xml,
- transitiveHTML: htmlDeps.Build(),
- transitiveText: textDeps.Build(),
- transitiveXML: xmlDeps.Build(),
+ depSets: depSetsBuilder.Build(),
}
if l.buildModuleReportZip {
- htmlZip := android.PathForModuleOut(ctx, "lint-report-html.zip")
- l.outputs.transitiveHTMLZip = android.OptionalPathForPath(htmlZip)
- lintZip(ctx, l.outputs.transitiveHTML.ToSortedList(), htmlZip)
-
- textZip := android.PathForModuleOut(ctx, "lint-report-text.zip")
- l.outputs.transitiveTextZip = android.OptionalPathForPath(textZip)
- lintZip(ctx, l.outputs.transitiveText.ToSortedList(), textZip)
-
- xmlZip := android.PathForModuleOut(ctx, "lint-report-xml.zip")
- l.outputs.transitiveXMLZip = android.OptionalPathForPath(xmlZip)
- lintZip(ctx, l.outputs.transitiveXML.ToSortedList(), xmlZip)
+ l.reports = BuildModuleLintReportZips(ctx, l.LintDepSets())
}
}
+func BuildModuleLintReportZips(ctx android.ModuleContext, depSets LintDepSets) android.Paths {
+ htmlList := depSets.HTML.ToSortedList()
+ textList := depSets.Text.ToSortedList()
+ xmlList := depSets.XML.ToSortedList()
+
+ if len(htmlList) == 0 && len(textList) == 0 && len(xmlList) == 0 {
+ return nil
+ }
+
+ htmlZip := android.PathForModuleOut(ctx, "lint-report-html.zip")
+ lintZip(ctx, htmlList, htmlZip)
+
+ textZip := android.PathForModuleOut(ctx, "lint-report-text.zip")
+ lintZip(ctx, textList, textZip)
+
+ xmlZip := android.PathForModuleOut(ctx, "lint-report-xml.zip")
+ lintZip(ctx, xmlList, xmlZip)
+
+ return android.Paths{htmlZip, textZip, xmlZip}
+}
+
type lintSingleton struct {
htmlZip android.WritablePath
textZip android.WritablePath
@@ -389,7 +457,7 @@
return
}
- if l, ok := m.(lintOutputIntf); ok {
+ if l, ok := m.(lintOutputsIntf); ok {
outputs = append(outputs, l.lintOutputs())
}
})
@@ -400,7 +468,9 @@
var paths android.Paths
for _, output := range outputs {
- paths = append(paths, get(output))
+ if p := get(output); p != nil {
+ paths = append(paths, p)
+ }
}
lintZip(ctx, paths, outputPath)
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 679c075..f2a509a 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -2011,6 +2011,15 @@
}
// to satisfy apex.javaDependency interface
+func (module *SdkLibraryImport) LintDepSets() LintDepSets {
+ if module.implLibraryModule == nil {
+ return LintDepSets{}
+ } else {
+ return module.implLibraryModule.LintDepSets()
+ }
+}
+
+// to satisfy apex.javaDependency interface
func (module *SdkLibraryImport) Stem() string {
return module.BaseModuleName()
}
diff --git a/ui/build/Android.bp b/ui/build/Android.bp
index 2a5a51a..4ef2721 100644
--- a/ui/build/Android.bp
+++ b/ui/build/Android.bp
@@ -56,12 +56,15 @@
"signal.go",
"soong.go",
"test_build.go",
+ "upload.go",
"util.go",
],
testSrcs: [
"cleanbuild_test.go",
"config_test.go",
"environment_test.go",
+ "rbe_test.go",
+ "upload_test.go",
"util_test.go",
"proc_sync_test.go",
],
diff --git a/ui/build/config.go b/ui/build/config.go
index 3a1188b..4490e1e 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -15,6 +15,7 @@
package build
import (
+ "fmt"
"os"
"path/filepath"
"runtime"
@@ -23,6 +24,10 @@
"time"
"android/soong/shared"
+
+ "github.com/golang/protobuf/proto"
+
+ smpb "android/soong/ui/metrics/metrics_proto"
)
type Config struct{ *configImpl }
@@ -181,10 +186,22 @@
"EMPTY_NINJA_FILE",
)
+ if ret.UseGoma() {
+ ctx.Println("Goma for Android is being deprecated and replaced with RBE. See go/rbe_for_android for instructions on how to use RBE.")
+ ctx.Println()
+ ctx.Println("See go/goma_android_exceptions for exceptions.")
+ ctx.Fatalln("USE_GOMA flag is no longer supported.")
+ }
+
+ if ret.ForceUseGoma() {
+ ret.environ.Set("USE_GOMA", "true")
+ }
+
// Tell python not to spam the source tree with .pyc files.
ret.environ.Set("PYTHONDONTWRITEBYTECODE", "1")
- ret.environ.Set("TMPDIR", absPath(ctx, ret.TempDir()))
+ tmpDir := absPath(ctx, ret.TempDir())
+ ret.environ.Set("TMPDIR", tmpDir)
// Always set ASAN_SYMBOLIZER_PATH so that ASAN-based tools can symbolize any crashes
symbolizerPath := filepath.Join("prebuilts/clang/host", ret.HostPrebuiltTag(),
@@ -256,12 +273,17 @@
ret.buildDateTime = strconv.FormatInt(time.Now().Unix(), 10)
}
- if ctx.Metrics != nil {
- ctx.Metrics.SetBuildDateTime(ret.buildDateTime)
- }
ret.environ.Set("BUILD_DATETIME_FILE", buildDateTimeFile)
- return Config{ret}
+ if ret.UseRBE() {
+ for k, v := range getRBEVars(ctx, Config{ret}) {
+ ret.environ.Set(k, v)
+ }
+ }
+
+ c := Config{ret}
+ storeConfigMetrics(ctx, c)
+ return c
}
// NewBuildActionConfig returns a build configuration based on the build action. The arguments are
@@ -270,6 +292,21 @@
return NewConfig(ctx, getConfigArgs(action, dir, ctx, args)...)
}
+// storeConfigMetrics selects a set of configuration information and store in
+// the metrics system for further analysis.
+func storeConfigMetrics(ctx Context, config Config) {
+ if ctx.Metrics == nil {
+ return
+ }
+
+ b := &smpb.BuildConfig{
+ ForceUseGoma: proto.Bool(config.ForceUseGoma()),
+ UseGoma: proto.Bool(config.UseGoma()),
+ UseRbe: proto.Bool(config.UseRBE()),
+ }
+ ctx.Metrics.BuildConfig(b)
+}
+
// getConfigArgs processes the command arguments based on the build action and creates a set of new
// arguments to be accepted by Config.
func getConfigArgs(action BuildAction, dir string, ctx Context, args []string) []string {
@@ -756,6 +793,18 @@
return c.totalRAM
}
+// ForceUseGoma determines whether we should override Goma deprecation
+// and use Goma for the current build or not.
+func (c *configImpl) ForceUseGoma() bool {
+ if v, ok := c.environ.Get("FORCE_USE_GOMA"); ok {
+ v = strings.TrimSpace(v)
+ if v != "" && v != "false" {
+ return true
+ }
+ }
+ return false
+}
+
func (c *configImpl) UseGoma() bool {
if v, ok := c.environ.Get("USE_GOMA"); ok {
v = strings.TrimSpace(v)
@@ -804,6 +853,75 @@
return true
}
+func (c *configImpl) logDir() string {
+ if c.Dist() {
+ return filepath.Join(c.DistDir(), "logs")
+ }
+ return c.OutDir()
+}
+
+func (c *configImpl) rbeStatsOutputDir() string {
+ for _, f := range []string{"RBE_output_dir", "FLAG_output_dir"} {
+ if v, ok := c.environ.Get(f); ok {
+ return v
+ }
+ }
+ return c.logDir()
+}
+
+func (c *configImpl) rbeLogPath() string {
+ for _, f := range []string{"RBE_log_path", "FLAG_log_path"} {
+ if v, ok := c.environ.Get(f); ok {
+ return v
+ }
+ }
+ return fmt.Sprintf("text://%v/reproxy_log.txt", c.logDir())
+}
+
+func (c *configImpl) rbeExecRoot() string {
+ for _, f := range []string{"RBE_exec_root", "FLAG_exec_root"} {
+ if v, ok := c.environ.Get(f); ok {
+ return v
+ }
+ }
+ wd, err := os.Getwd()
+ if err != nil {
+ return ""
+ }
+ return wd
+}
+
+func (c *configImpl) rbeDir() string {
+ if v, ok := c.environ.Get("RBE_DIR"); ok {
+ return v
+ }
+ return "prebuilts/remoteexecution-client/live/"
+}
+
+func (c *configImpl) rbeReproxy() string {
+ for _, f := range []string{"RBE_re_proxy", "FLAG_re_proxy"} {
+ if v, ok := c.environ.Get(f); ok {
+ return v
+ }
+ }
+ return filepath.Join(c.rbeDir(), "reproxy")
+}
+
+func (c *configImpl) rbeAuth() (string, string) {
+ credFlags := []string{"use_application_default_credentials", "use_gce_credentials", "credential_file"}
+ for _, cf := range credFlags {
+ for _, f := range []string{"RBE_" + cf, "FLAG_" + cf} {
+ if v, ok := c.environ.Get(f); ok {
+ v = strings.TrimSpace(v)
+ if v != "" && v != "false" && v != "0" {
+ return "RBE_" + cf, v
+ }
+ }
+ }
+ }
+ return "RBE_use_application_default_credentials", "true"
+}
+
func (c *configImpl) UseRemoteBuild() bool {
return c.UseGoma() || c.UseRBE()
}
@@ -962,3 +1080,14 @@
func (c *configImpl) IsPdkBuild() bool {
return c.pdkBuild
}
+
+func (c *configImpl) BuildDateTime() string {
+ return c.buildDateTime
+}
+
+func (c *configImpl) MetricsUploaderApp() string {
+ if p, ok := c.environ.Get("ANDROID_ENABLE_METRICS_UPLOAD"); ok {
+ return p
+ }
+ return ""
+}
diff --git a/ui/build/config_test.go b/ui/build/config_test.go
index df618c4..7b14c47 100644
--- a/ui/build/config_test.go
+++ b/ui/build/config_test.go
@@ -26,6 +26,7 @@
"testing"
"android/soong/ui/logger"
+ "android/soong/ui/status"
)
func testContext() Context {
@@ -33,6 +34,7 @@
Context: context.Background(),
Logger: logger.New(&bytes.Buffer{}),
Writer: &bytes.Buffer{},
+ Status: &status.Status{},
}}
}
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index a3234e3..bd073e5 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -54,18 +54,16 @@
var ret map[string]string
if len(makeVars) > 0 {
+ // It's not safe to use the same TMPDIR as the build, as that can be removed.
tmpDir, err := ioutil.TempDir("", "dumpvars")
if err != nil {
return nil, err
}
defer os.RemoveAll(tmpDir)
- // It's not safe to use the same TMPDIR as the build, as that can be removed.
- config.Environment().Set("TMPDIR", tmpDir)
+ SetupLitePath(ctx, config, tmpDir)
- SetupLitePath(ctx, config)
-
- ret, err = dumpMakeVars(ctx, config, goals, makeVars, false)
+ ret, err = dumpMakeVars(ctx, config, goals, makeVars, false, tmpDir)
if err != nil {
return ret, err
}
@@ -82,7 +80,7 @@
return ret, nil
}
-func dumpMakeVars(ctx Context, config Config, goals, vars []string, write_soong_vars bool) (map[string]string, error) {
+func dumpMakeVars(ctx Context, config Config, goals, vars []string, write_soong_vars bool, tmpDir string) (map[string]string, error) {
ctx.BeginTrace(metrics.RunKati, "dumpvars")
defer ctx.EndTrace()
@@ -98,6 +96,9 @@
cmd.Environment.Set("WRITE_SOONG_VARIABLES", "true")
}
cmd.Environment.Set("DUMP_MANY_VARS", strings.Join(vars, " "))
+ if tmpDir != "" {
+ cmd.Environment.Set("TMPDIR", tmpDir)
+ }
cmd.Sandbox = dumpvarsSandbox
output := bytes.Buffer{}
cmd.Stdout = &output
@@ -262,7 +263,7 @@
"BUILD_BROKEN_USES_BUILD_TARGET_TEST_CONFIG",
}, exportEnvVars...), BannerVars...)
- make_vars, err := dumpMakeVars(ctx, config, config.Arguments(), allVars, true)
+ make_vars, err := dumpMakeVars(ctx, config, config.Arguments(), allVars, true, "")
if err != nil {
ctx.Fatalln("Error dumping make vars:", err)
}
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index 4fc1f01..dfc3be1 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -128,6 +128,16 @@
"GOMA_USE_LOCAL",
// RBE client
+ "RBE_compare",
+ "RBE_exec_root",
+ "RBE_exec_strategy",
+ "RBE_invocation_id",
+ "RBE_log_dir",
+ "RBE_platform",
+ "RBE_remote_accept_cache",
+ "RBE_remote_update_cache",
+ "RBE_server_address",
+ // TODO: remove old FLAG_ variables.
"FLAG_compare",
"FLAG_exec_root",
"FLAG_exec_strategy",
diff --git a/ui/build/path.go b/ui/build/path.go
index c34ba1b..f515775 100644
--- a/ui/build/path.go
+++ b/ui/build/path.go
@@ -55,8 +55,9 @@
}
// A "lite" version of SetupPath used for dumpvars, or other places that need
-// minimal overhead (but at the expense of logging).
-func SetupLitePath(ctx Context, config Config) {
+// minimal overhead (but at the expense of logging). If tmpDir is empty, the
+// default TMPDIR is used from config.
+func SetupLitePath(ctx Context, config Config, tmpDir string) {
if config.pathReplaced {
return
}
@@ -65,8 +66,11 @@
defer ctx.EndTrace()
origPath, _ := config.Environment().Get("PATH")
- myPath, _ := config.Environment().Get("TMPDIR")
- myPath = filepath.Join(myPath, "path")
+
+ if tmpDir == "" {
+ tmpDir, _ = config.Environment().Get("TMPDIR")
+ }
+ myPath := filepath.Join(tmpDir, "path")
ensureEmptyDirectoriesExist(ctx, myPath)
os.Setenv("PATH", origPath)
diff --git a/ui/build/rbe.go b/ui/build/rbe.go
index ceea4bf..6a26063 100644
--- a/ui/build/rbe.go
+++ b/ui/build/rbe.go
@@ -15,14 +15,57 @@
package build
import (
+ "fmt"
+ "math/rand"
+ "os"
"path/filepath"
+ "time"
"android/soong/ui/metrics"
)
-const bootstrapCmd = "bootstrap"
-const rbeLeastNProcs = 2500
-const rbeLeastNFiles = 16000
+const (
+ rbeLeastNProcs = 2500
+ rbeLeastNFiles = 16000
+
+ // prebuilt RBE binaries
+ bootstrapCmd = "bootstrap"
+
+ // RBE metrics proto buffer file
+ rbeMetricsPBFilename = "rbe_metrics.pb"
+)
+
+func rbeCommand(ctx Context, config Config, rbeCmd string) string {
+ var cmdPath string
+ if rbeDir := config.rbeDir(); rbeDir != "" {
+ cmdPath = filepath.Join(rbeDir, rbeCmd)
+ } else {
+ ctx.Fatalf("rbe command path not found")
+ }
+
+ if _, err := os.Stat(cmdPath); err != nil && os.IsNotExist(err) {
+ ctx.Fatalf("rbe command %q not found", rbeCmd)
+ }
+
+ return cmdPath
+}
+
+func getRBEVars(ctx Context, config Config) map[string]string {
+ rand.Seed(time.Now().UnixNano())
+ vars := map[string]string{
+ "RBE_log_path": config.rbeLogPath(),
+ "RBE_log_dir": config.logDir(),
+ "RBE_re_proxy": config.rbeReproxy(),
+ "RBE_exec_root": config.rbeExecRoot(),
+ "RBE_output_dir": config.rbeStatsOutputDir(),
+ }
+ if config.StartRBE() {
+ vars["RBE_server_address"] = fmt.Sprintf("unix://%v/reproxy_%v.sock", absPath(ctx, config.TempDir()), rand.Intn(1000))
+ }
+ k, v := config.rbeAuth()
+ vars[k] = v
+ return vars
+}
func startRBE(ctx Context, config Config) {
ctx.BeginTrace(metrics.RunSetupTool, "rbe_bootstrap")
@@ -35,18 +78,53 @@
ctx.Fatalf("max open files is insufficient: %d; want >= %d.\n", n, rbeLeastNFiles)
}
- var rbeBootstrap string
- if rbeDir, ok := config.Environment().Get("RBE_DIR"); ok {
- rbeBootstrap = filepath.Join(rbeDir, bootstrapCmd)
- } else if home, ok := config.Environment().Get("HOME"); ok {
- rbeBootstrap = filepath.Join(home, "rbe", bootstrapCmd)
- } else {
- ctx.Fatalln("rbe bootstrap not found")
- }
-
- cmd := Command(ctx, config, "boostrap", rbeBootstrap)
+ cmd := Command(ctx, config, "startRBE bootstrap", rbeCommand(ctx, config, bootstrapCmd))
if output, err := cmd.CombinedOutput(); err != nil {
ctx.Fatalf("rbe bootstrap failed with: %v\n%s\n", err, output)
}
}
+
+func stopRBE(ctx Context, config Config) {
+ cmd := Command(ctx, config, "stopRBE bootstrap", rbeCommand(ctx, config, bootstrapCmd), "-shutdown")
+ if output, err := cmd.CombinedOutput(); err != nil {
+ ctx.Fatalf("rbe bootstrap with shutdown failed with: %v\n%s\n", err, output)
+ }
+}
+
+// DumpRBEMetrics creates a metrics protobuf file containing RBE related metrics.
+// The protobuf file is created if RBE is enabled and the proxy service has
+// started. The proxy service is shutdown in order to dump the RBE metrics to the
+// protobuf file.
+func DumpRBEMetrics(ctx Context, config Config, filename string) {
+ ctx.BeginTrace(metrics.RunShutdownTool, "dump_rbe_metrics")
+ defer ctx.EndTrace()
+
+ // Remove the previous metrics file in case there is a failure or RBE has been
+ // disable for this run.
+ os.Remove(filename)
+
+ // If RBE is not enabled then there are no metrics to generate.
+ // If RBE does not require to start, the RBE proxy maybe started
+ // manually for debugging purpose and can generate the metrics
+ // afterwards.
+ if !config.StartRBE() {
+ return
+ }
+
+ outputDir := config.rbeStatsOutputDir()
+ if outputDir == "" {
+ ctx.Fatal("RBE output dir variable not defined. Aborting metrics dumping.")
+ }
+ metricsFile := filepath.Join(outputDir, rbeMetricsPBFilename)
+
+ // Stop the proxy first in order to generate the RBE metrics protobuf file.
+ stopRBE(ctx, config)
+
+ if metricsFile == filename {
+ return
+ }
+ if _, err := copyFile(metricsFile, filename); err != nil {
+ ctx.Fatalf("failed to copy %q to %q: %v\n", metricsFile, filename, err)
+ }
+}
diff --git a/ui/build/rbe_test.go b/ui/build/rbe_test.go
new file mode 100644
index 0000000..c56a33c
--- /dev/null
+++ b/ui/build/rbe_test.go
@@ -0,0 +1,142 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package build
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+
+ "android/soong/ui/logger"
+)
+
+func TestDumpRBEMetrics(t *testing.T) {
+ ctx := testContext()
+ tests := []struct {
+ description string
+ env []string
+ generated bool
+ }{{
+ description: "RBE disabled",
+ env: []string{
+ "NOSTART_RBE=true",
+ },
+ }, {
+ description: "rbe metrics generated",
+ env: []string{
+ "USE_RBE=true",
+ },
+ generated: true,
+ }}
+
+ for _, tt := range tests {
+ t.Run(tt.description, func(t *testing.T) {
+ tmpDir, err := ioutil.TempDir("", "")
+ if err != nil {
+ t.Fatalf("failed to create a temp directory: %v", err)
+ }
+ defer os.RemoveAll(tmpDir)
+
+ rbeBootstrapCmd := filepath.Join(tmpDir, bootstrapCmd)
+ if err := ioutil.WriteFile(rbeBootstrapCmd, []byte(rbeBootstrapProgram), 0755); err != nil {
+ t.Fatalf("failed to create a fake bootstrap command file %s: %v", rbeBootstrapCmd, err)
+ }
+
+ env := Environment(tt.env)
+ env.Set("OUT_DIR", tmpDir)
+ env.Set("RBE_DIR", tmpDir)
+
+ tmpRBEDir, err := ioutil.TempDir("", "")
+ if err != nil {
+ t.Fatalf("failed to create a temp directory for RBE: %v", err)
+ }
+ defer os.RemoveAll(tmpRBEDir)
+ env.Set("RBE_output_dir", tmpRBEDir)
+
+ config := Config{&configImpl{
+ environ: &env,
+ }}
+
+ rbeMetricsFilename := filepath.Join(tmpDir, rbeMetricsPBFilename)
+ DumpRBEMetrics(ctx, config, rbeMetricsFilename)
+
+ // Validate that the rbe metrics file exists if RBE is enabled.
+ if _, err := os.Stat(rbeMetricsFilename); err == nil {
+ if !tt.generated {
+ t.Errorf("got true, want false for rbe metrics file %s to exist.", rbeMetricsFilename)
+ }
+ } else if os.IsNotExist(err) {
+ if tt.generated {
+ t.Errorf("got false, want true for rbe metrics file %s to exist.", rbeMetricsFilename)
+ }
+ } else {
+ t.Errorf("unknown error found on checking %s exists: %v", rbeMetricsFilename, err)
+ }
+ })
+ }
+}
+
+func TestDumpRBEMetricsErrors(t *testing.T) {
+ ctx := testContext()
+ tests := []struct {
+ description string
+ bootstrapProgram string
+ expectedErr string
+ }{{
+ description: "stopRBE failed",
+ bootstrapProgram: "#!/bin/bash\nexit 1\n",
+ expectedErr: "shutdown failed",
+ }}
+
+ for _, tt := range tests {
+ t.Run(tt.description, func(t *testing.T) {
+ defer logger.Recover(func(err error) {
+ got := err.Error()
+ if !strings.Contains(got, tt.expectedErr) {
+ t.Errorf("got %q, want %q to be contained in error", got, tt.expectedErr)
+ }
+ })
+
+ tmpDir, err := ioutil.TempDir("", "")
+ if err != nil {
+ t.Fatalf("failed to create a temp directory: %v", err)
+ }
+ defer os.RemoveAll(tmpDir)
+
+ rbeBootstrapCmd := filepath.Join(tmpDir, bootstrapCmd)
+ if err := ioutil.WriteFile(rbeBootstrapCmd, []byte(tt.bootstrapProgram), 0755); err != nil {
+ t.Fatalf("failed to create a fake bootstrap command file %s: %v", rbeBootstrapCmd, err)
+ }
+
+ env := &Environment{}
+ env.Set("USE_RBE", "true")
+ env.Set("OUT_DIR", tmpDir)
+ env.Set("RBE_DIR", tmpDir)
+
+ config := Config{&configImpl{
+ environ: env,
+ }}
+
+ rbeMetricsFilename := filepath.Join(tmpDir, rbeMetricsPBFilename)
+ DumpRBEMetrics(ctx, config, rbeMetricsFilename)
+ t.Errorf("got nil, expecting %q as a failure", tt.expectedErr)
+ })
+ }
+}
+
+var rbeBootstrapProgram = fmt.Sprintf("#!/bin/bash\necho 1 > $RBE_output_dir/%s\n", rbeMetricsPBFilename)
diff --git a/ui/build/upload.go b/ui/build/upload.go
new file mode 100644
index 0000000..1cc2e94
--- /dev/null
+++ b/ui/build/upload.go
@@ -0,0 +1,113 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package build
+
+// This file contains the functionality to upload data from one location to
+// another.
+
+import (
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "time"
+
+ "android/soong/ui/metrics"
+ "github.com/golang/protobuf/proto"
+
+ upload_proto "android/soong/ui/metrics/upload_proto"
+)
+
+const (
+ uploadPbFilename = ".uploader.pb"
+)
+
+var (
+ // For testing purpose
+ getTmpDir = ioutil.TempDir
+)
+
+// UploadMetrics uploads a set of metrics files to a server for analysis. An
+// uploader full path is required to be specified in order to upload the set
+// of metrics files. This is accomplished by defining the ANDROID_ENABLE_METRICS_UPLOAD
+// environment variable. The metrics files are copied to a temporary directory
+// and the uploader is then executed in the background to allow the user to continue
+// working.
+func UploadMetrics(ctx Context, config Config, forceDumbOutput bool, buildStarted time.Time, files ...string) {
+ ctx.BeginTrace(metrics.RunSetupTool, "upload_metrics")
+ defer ctx.EndTrace()
+
+ uploader := config.MetricsUploaderApp()
+ // No metrics to upload if the path to the uploader was not specified.
+ if uploader == "" {
+ return
+ }
+
+ // Some files may not exist. For example, build errors protobuf file
+ // may not exist since the build was successful.
+ var metricsFiles []string
+ for _, f := range files {
+ if _, err := os.Stat(f); err == nil {
+ metricsFiles = append(metricsFiles, f)
+ }
+ }
+
+ if len(metricsFiles) == 0 {
+ return
+ }
+
+ // The temporary directory cannot be deleted as the metrics uploader is started
+ // in the background and requires to exist until the operation is done. The
+ // uploader can delete the directory as it is specified in the upload proto.
+ tmpDir, err := getTmpDir("", "upload_metrics")
+ if err != nil {
+ ctx.Fatalf("failed to create a temporary directory to store the list of metrics files: %v\n", err)
+ }
+
+ for i, src := range metricsFiles {
+ dst := filepath.Join(tmpDir, filepath.Base(src))
+ if _, err := copyFile(src, dst); err != nil {
+ ctx.Fatalf("failed to copy %q to %q: %v\n", src, dst, err)
+ }
+ metricsFiles[i] = dst
+ }
+
+ // For platform builds, the branch and target name is hardcoded to specific
+ // values for later extraction of the metrics in the data metrics pipeline.
+ data, err := proto.Marshal(&upload_proto.Upload{
+ CreationTimestampMs: proto.Uint64(uint64(buildStarted.UnixNano() / int64(time.Millisecond))),
+ CompletionTimestampMs: proto.Uint64(uint64(time.Now().UnixNano() / int64(time.Millisecond))),
+ BranchName: proto.String("developer-metrics"),
+ TargetName: proto.String("platform-build-systems-metrics"),
+ MetricsFiles: metricsFiles,
+ DirectoriesToDelete: []string{tmpDir},
+ })
+ if err != nil {
+ ctx.Fatalf("failed to marshal metrics upload proto buffer message: %v\n", err)
+ }
+
+ pbFile := filepath.Join(tmpDir, uploadPbFilename)
+ if err := ioutil.WriteFile(pbFile, data, 0644); err != nil {
+ ctx.Fatalf("failed to write the marshaled metrics upload protobuf to %q: %v\n", pbFile, err)
+ }
+
+ // Start the uploader in the background as it takes several milliseconds to start the uploader
+ // and prepare the metrics for upload. This affects small commands like "lunch".
+ cmd := Command(ctx, config, "upload metrics", uploader, "--upload-metrics", pbFile)
+ if forceDumbOutput {
+ cmd.RunOrFatal()
+ } else {
+ cmd.RunAndStreamOrFatal()
+ }
+}
diff --git a/ui/build/upload_test.go b/ui/build/upload_test.go
new file mode 100644
index 0000000..dccf156
--- /dev/null
+++ b/ui/build/upload_test.go
@@ -0,0 +1,158 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package build
+
+import (
+ "errors"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strconv"
+ "strings"
+ "testing"
+ "time"
+
+ "android/soong/ui/logger"
+)
+
+func TestUploadMetrics(t *testing.T) {
+ ctx := testContext()
+ tests := []struct {
+ description string
+ uploader string
+ createFiles bool
+ files []string
+ }{{
+ description: "ANDROID_ENABLE_METRICS_UPLOAD not set",
+ }, {
+ description: "no metrics files to upload",
+ uploader: "fake",
+ }, {
+ description: "non-existent metrics files no upload",
+ uploader: "fake",
+ files: []string{"metrics_file_1", "metrics_file_2", "metrics_file_3"},
+ }, {
+ description: "trigger upload",
+ uploader: "echo",
+ createFiles: true,
+ files: []string{"metrics_file_1", "metrics_file_2"},
+ }}
+
+ for _, tt := range tests {
+ t.Run(tt.description, func(t *testing.T) {
+ defer logger.Recover(func(err error) {
+ t.Fatalf("got unexpected error: %v", err)
+ })
+
+ outDir, err := ioutil.TempDir("", "")
+ if err != nil {
+ t.Fatalf("failed to create out directory: %v", outDir)
+ }
+ defer os.RemoveAll(outDir)
+
+ // Supply our own getTmpDir to delete the temp dir once the test is done.
+ orgGetTmpDir := getTmpDir
+ getTmpDir = func(string, string) (string, error) {
+ retDir := filepath.Join(outDir, "tmp_upload_dir")
+ if err := os.Mkdir(retDir, 0755); err != nil {
+ t.Fatalf("failed to create temporary directory %q: %v", retDir, err)
+ }
+ return retDir, nil
+ }
+ defer func() { getTmpDir = orgGetTmpDir }()
+
+ metricsUploadDir := filepath.Join(outDir, ".metrics_uploader")
+ if err := os.Mkdir(metricsUploadDir, 0755); err != nil {
+ t.Fatalf("failed to create %q directory for oauth valid check: %v", metricsUploadDir, err)
+ }
+
+ var metricsFiles []string
+ if tt.createFiles {
+ for _, f := range tt.files {
+ filename := filepath.Join(outDir, f)
+ metricsFiles = append(metricsFiles, filename)
+ if err := ioutil.WriteFile(filename, []byte("test file"), 0644); err != nil {
+ t.Fatalf("failed to create a fake metrics file %q for uploading: %v", filename, err)
+ }
+ }
+ }
+
+ config := Config{&configImpl{
+ environ: &Environment{
+ "OUT_DIR=" + outDir,
+ "ANDROID_ENABLE_METRICS_UPLOAD=" + tt.uploader,
+ },
+ buildDateTime: strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10),
+ }}
+
+ UploadMetrics(ctx, config, false, time.Now(), metricsFiles...)
+ })
+ }
+}
+
+func TestUploadMetricsErrors(t *testing.T) {
+ ctx := testContext()
+ tests := []struct {
+ description string
+ tmpDir string
+ tmpDirErr error
+ expectedErr string
+ }{{
+ description: "getTmpDir returned error",
+ tmpDirErr: errors.New("getTmpDir failed"),
+ expectedErr: "getTmpDir failed",
+ }, {
+ description: "copyFile operation error",
+ tmpDir: "/fake_dir",
+ expectedErr: "failed to copy",
+ }}
+
+ for _, tt := range tests {
+ t.Run(tt.description, func(t *testing.T) {
+ defer logger.Recover(func(err error) {
+ got := err.Error()
+ if !strings.Contains(got, tt.expectedErr) {
+ t.Errorf("got %q, want %q to be contained in error", got, tt.expectedErr)
+ }
+ })
+
+ outDir, err := ioutil.TempDir("", "")
+ if err != nil {
+ t.Fatalf("failed to create out directory: %v", outDir)
+ }
+ defer os.RemoveAll(outDir)
+
+ orgGetTmpDir := getTmpDir
+ getTmpDir = func(string, string) (string, error) {
+ return tt.tmpDir, tt.tmpDirErr
+ }
+ defer func() { getTmpDir = orgGetTmpDir }()
+
+ metricsFile := filepath.Join(outDir, "metrics_file_1")
+ if err := ioutil.WriteFile(metricsFile, []byte("test file"), 0644); err != nil {
+ t.Fatalf("failed to create a fake metrics file %q for uploading: %v", metricsFile, err)
+ }
+
+ config := Config{&configImpl{
+ environ: &Environment{
+ "ANDROID_ENABLE_METRICS_UPLOAD=fake",
+ "OUT_DIR=/bad",
+ }}}
+
+ UploadMetrics(ctx, config, true, time.Now(), metricsFile)
+ t.Errorf("got nil, expecting %q as a failure", tt.expectedErr)
+ })
+ }
+}
diff --git a/ui/build/util.go b/ui/build/util.go
index 75e6753..d44cd6d 100644
--- a/ui/build/util.go
+++ b/ui/build/util.go
@@ -15,6 +15,7 @@
package build
import (
+ "io"
"os"
"path/filepath"
"strings"
@@ -124,3 +125,20 @@
}
return str[:idx], str[idx+1:], true
}
+
+// copyFile copies a file from src to dst. filepath.Dir(dst) must exist.
+func copyFile(src, dst string) (int64, error) {
+ source, err := os.Open(src)
+ if err != nil {
+ return 0, err
+ }
+ defer source.Close()
+
+ destination, err := os.Create(dst)
+ if err != nil {
+ return 0, err
+ }
+ defer destination.Close()
+
+ return io.Copy(destination, source)
+}
diff --git a/ui/build/util_test.go b/ui/build/util_test.go
index 89bfc77..b22e997 100644
--- a/ui/build/util_test.go
+++ b/ui/build/util_test.go
@@ -15,6 +15,7 @@
package build
import (
+ "bytes"
"io/ioutil"
"os"
"path/filepath"
@@ -49,3 +50,72 @@
ensureEmptyDirectoriesExist(ctx, filepath.Join(tmpDir, "a"))
}
+
+func TestCopyFile(t *testing.T) {
+ tmpDir, err := ioutil.TempDir("", "test_copy_file")
+ if err != nil {
+ t.Fatalf("failed to create temporary directory to hold test text files: %v", err)
+ }
+ defer os.Remove(tmpDir)
+
+ data := []byte("fake data")
+ src := filepath.Join(tmpDir, "src.txt")
+ if err := ioutil.WriteFile(src, data, 0755); err != nil {
+ t.Fatalf("failed to create a src file %q for copying: %v", src, err)
+ }
+
+ dst := filepath.Join(tmpDir, "dst.txt")
+
+ l, err := copyFile(src, dst)
+ if err != nil {
+ t.Fatalf("got %v, expecting nil error on copyFile operation", err)
+ }
+
+ if l != int64(len(data)) {
+ t.Errorf("got %d, expecting %d for copied bytes", l, len(data))
+ }
+
+ dstData, err := ioutil.ReadFile(dst)
+ if err != nil {
+ t.Fatalf("got %v, expecting nil error reading dst %q file", err, dst)
+ }
+
+ if bytes.Compare(data, dstData) != 0 {
+ t.Errorf("got %q, expecting data %q from dst %q text file", string(data), string(dstData), dst)
+ }
+}
+
+func TestCopyFileErrors(t *testing.T) {
+ tmpDir, err := ioutil.TempDir("", "test_copy_file_errors")
+ if err != nil {
+ t.Fatalf("failed to create temporary directory to hold test text files: %v", err)
+ }
+ defer os.Remove(tmpDir)
+
+ srcExists := filepath.Join(tmpDir, "src_exist.txt")
+ if err := ioutil.WriteFile(srcExists, []byte("fake data"), 0755); err != nil {
+ t.Fatalf("failed to create a src file %q for copying: %v", srcExists, err)
+ }
+
+ tests := []struct {
+ description string
+ src string
+ dst string
+ }{{
+ description: "src file does not exist",
+ src: "/src/not/exist",
+ dst: "/dst/not/exist",
+ }, {
+ description: "dst directory does not exist",
+ src: srcExists,
+ dst: "/dst/not/exist",
+ }}
+
+ for _, tt := range tests {
+ t.Run(tt.description, func(t *testing.T) {
+ if _, err := copyFile(tt.src, tt.dst); err == nil {
+ t.Errorf("got nil, expecting error")
+ }
+ })
+ }
+}
diff --git a/ui/metrics/Android.bp b/ui/metrics/Android.bp
index 529639d..8188a69 100644
--- a/ui/metrics/Android.bp
+++ b/ui/metrics/Android.bp
@@ -17,6 +17,7 @@
pkgPath: "android/soong/ui/metrics",
deps: [
"golang-protobuf-proto",
+ "soong-ui-metrics_upload_proto",
"soong-ui-metrics_proto",
"soong-ui-tracer",
],
@@ -24,6 +25,9 @@
"metrics.go",
"time.go",
],
+ testSrcs: [
+ "time_test.go",
+ ],
}
bootstrap_go_package {
@@ -35,3 +39,11 @@
],
}
+bootstrap_go_package {
+ name: "soong-ui-metrics_upload_proto",
+ pkgPath: "android/soong/ui/metrics/upload_proto",
+ deps: ["golang-protobuf-proto"],
+ srcs: [
+ "upload_proto/upload.pb.go",
+ ],
+}
diff --git a/ui/metrics/metrics.go b/ui/metrics/metrics.go
index 8254e4a..65cae4a 100644
--- a/ui/metrics/metrics.go
+++ b/ui/metrics/metrics.go
@@ -17,7 +17,8 @@
import (
"io/ioutil"
"os"
- "strconv"
+ "runtime"
+ "time"
"github.com/golang/protobuf/proto"
@@ -25,12 +26,13 @@
)
const (
- RunSetupTool = "setup"
- RunKati = "kati"
- RunSoong = "soong"
- PrimaryNinja = "ninja"
- TestRun = "test"
- Total = "total"
+ PrimaryNinja = "ninja"
+ RunKati = "kati"
+ RunSetupTool = "setup"
+ RunShutdownTool = "shutdown"
+ RunSoong = "soong"
+ TestRun = "test"
+ Total = "total"
)
type Metrics struct {
@@ -64,6 +66,10 @@
}
}
+func (m *Metrics) BuildConfig(b *soong_metrics_proto.BuildConfig) {
+ m.metrics.BuildConfig = b
+}
+
func (m *Metrics) SetMetadataMetrics(metadata map[string]string) {
for k, v := range metadata {
switch k {
@@ -97,8 +103,6 @@
m.metrics.HostArch = m.getArch(v)
case "HOST_2ND_ARCH":
m.metrics.Host_2NdArch = m.getArch(v)
- case "HOST_OS":
- m.metrics.HostOs = proto.String(v)
case "HOST_OS_EXTRA":
m.metrics.HostOsExtra = proto.String(v)
case "HOST_CROSS_OS":
@@ -130,18 +134,13 @@
}
}
-func (m *Metrics) SetBuildDateTime(date_time string) {
- if date_time != "" {
- date_time_timestamp, err := strconv.ParseInt(date_time, 10, 64)
- if err != nil {
- panic(err)
- }
- m.metrics.BuildDateTimestamp = &date_time_timestamp
- }
+func (m *Metrics) SetBuildDateTime(buildTimestamp time.Time) {
+ m.metrics.BuildDateTimestamp = proto.Int64(buildTimestamp.UnixNano() / int64(time.Second))
}
// exports the output to the file at outputPath
func (m *Metrics) Dump(outputPath string) (err error) {
+ m.metrics.HostOs = proto.String(runtime.GOOS)
return writeMessageToFile(&m.metrics, outputPath)
}
diff --git a/ui/metrics/metrics_proto/metrics.pb.go b/ui/metrics/metrics_proto/metrics.pb.go
index 3986d0e..84706b2 100644
--- a/ui/metrics/metrics_proto/metrics.pb.go
+++ b/ui/metrics/metrics_proto/metrics.pb.go
@@ -152,7 +152,7 @@
}
func (ModuleTypeInfo_BuildSystem) EnumDescriptor() ([]byte, []int) {
- return fileDescriptor_6039342a2ba47b72, []int{2, 0}
+ return fileDescriptor_6039342a2ba47b72, []int{3, 0}
}
type MetricsBase struct {
@@ -197,10 +197,11 @@
// The metrics for calling Ninja.
NinjaRuns []*PerfInfo `protobuf:"bytes,20,rep,name=ninja_runs,json=ninjaRuns" json:"ninja_runs,omitempty"`
// The metrics for the whole build
- Total *PerfInfo `protobuf:"bytes,21,opt,name=total" json:"total,omitempty"`
- XXX_NoUnkeyedLiteral struct{} `json:"-"`
- XXX_unrecognized []byte `json:"-"`
- XXX_sizecache int32 `json:"-"`
+ Total *PerfInfo `protobuf:"bytes,21,opt,name=total" json:"total,omitempty"`
+ BuildConfig *BuildConfig `protobuf:"bytes,23,opt,name=build_config,json=buildConfig" json:"build_config,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
func (m *MetricsBase) Reset() { *m = MetricsBase{} }
@@ -380,6 +381,68 @@
return nil
}
+func (m *MetricsBase) GetBuildConfig() *BuildConfig {
+ if m != nil {
+ return m.BuildConfig
+ }
+ return nil
+}
+
+type BuildConfig struct {
+ UseGoma *bool `protobuf:"varint,1,opt,name=use_goma,json=useGoma" json:"use_goma,omitempty"`
+ UseRbe *bool `protobuf:"varint,2,opt,name=use_rbe,json=useRbe" json:"use_rbe,omitempty"`
+ ForceUseGoma *bool `protobuf:"varint,3,opt,name=force_use_goma,json=forceUseGoma" json:"force_use_goma,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *BuildConfig) Reset() { *m = BuildConfig{} }
+func (m *BuildConfig) String() string { return proto.CompactTextString(m) }
+func (*BuildConfig) ProtoMessage() {}
+func (*BuildConfig) Descriptor() ([]byte, []int) {
+ return fileDescriptor_6039342a2ba47b72, []int{1}
+}
+
+func (m *BuildConfig) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_BuildConfig.Unmarshal(m, b)
+}
+func (m *BuildConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_BuildConfig.Marshal(b, m, deterministic)
+}
+func (m *BuildConfig) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_BuildConfig.Merge(m, src)
+}
+func (m *BuildConfig) XXX_Size() int {
+ return xxx_messageInfo_BuildConfig.Size(m)
+}
+func (m *BuildConfig) XXX_DiscardUnknown() {
+ xxx_messageInfo_BuildConfig.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_BuildConfig proto.InternalMessageInfo
+
+func (m *BuildConfig) GetUseGoma() bool {
+ if m != nil && m.UseGoma != nil {
+ return *m.UseGoma
+ }
+ return false
+}
+
+func (m *BuildConfig) GetUseRbe() bool {
+ if m != nil && m.UseRbe != nil {
+ return *m.UseRbe
+ }
+ return false
+}
+
+func (m *BuildConfig) GetForceUseGoma() bool {
+ if m != nil && m.ForceUseGoma != nil {
+ return *m.ForceUseGoma
+ }
+ return false
+}
+
type PerfInfo struct {
// The description for the phase/action/part while the tool running.
Desc *string `protobuf:"bytes,1,opt,name=desc" json:"desc,omitempty"`
@@ -402,7 +465,7 @@
func (m *PerfInfo) String() string { return proto.CompactTextString(m) }
func (*PerfInfo) ProtoMessage() {}
func (*PerfInfo) Descriptor() ([]byte, []int) {
- return fileDescriptor_6039342a2ba47b72, []int{1}
+ return fileDescriptor_6039342a2ba47b72, []int{2}
}
func (m *PerfInfo) XXX_Unmarshal(b []byte) error {
@@ -474,7 +537,7 @@
func (m *ModuleTypeInfo) String() string { return proto.CompactTextString(m) }
func (*ModuleTypeInfo) ProtoMessage() {}
func (*ModuleTypeInfo) Descriptor() ([]byte, []int) {
- return fileDescriptor_6039342a2ba47b72, []int{2}
+ return fileDescriptor_6039342a2ba47b72, []int{3}
}
func (m *ModuleTypeInfo) XXX_Unmarshal(b []byte) error {
@@ -532,7 +595,7 @@
func (m *CriticalUserJourneyMetrics) String() string { return proto.CompactTextString(m) }
func (*CriticalUserJourneyMetrics) ProtoMessage() {}
func (*CriticalUserJourneyMetrics) Descriptor() ([]byte, []int) {
- return fileDescriptor_6039342a2ba47b72, []int{3}
+ return fileDescriptor_6039342a2ba47b72, []int{4}
}
func (m *CriticalUserJourneyMetrics) XXX_Unmarshal(b []byte) error {
@@ -579,7 +642,7 @@
func (m *CriticalUserJourneysMetrics) String() string { return proto.CompactTextString(m) }
func (*CriticalUserJourneysMetrics) ProtoMessage() {}
func (*CriticalUserJourneysMetrics) Descriptor() ([]byte, []int) {
- return fileDescriptor_6039342a2ba47b72, []int{4}
+ return fileDescriptor_6039342a2ba47b72, []int{5}
}
func (m *CriticalUserJourneysMetrics) XXX_Unmarshal(b []byte) error {
@@ -612,6 +675,7 @@
proto.RegisterEnum("soong_build_metrics.MetricsBase_Arch", MetricsBase_Arch_name, MetricsBase_Arch_value)
proto.RegisterEnum("soong_build_metrics.ModuleTypeInfo_BuildSystem", ModuleTypeInfo_BuildSystem_name, ModuleTypeInfo_BuildSystem_value)
proto.RegisterType((*MetricsBase)(nil), "soong_build_metrics.MetricsBase")
+ proto.RegisterType((*BuildConfig)(nil), "soong_build_metrics.BuildConfig")
proto.RegisterType((*PerfInfo)(nil), "soong_build_metrics.PerfInfo")
proto.RegisterType((*ModuleTypeInfo)(nil), "soong_build_metrics.ModuleTypeInfo")
proto.RegisterType((*CriticalUserJourneyMetrics)(nil), "soong_build_metrics.CriticalUserJourneyMetrics")
@@ -621,58 +685,63 @@
func init() { proto.RegisterFile("metrics.proto", fileDescriptor_6039342a2ba47b72) }
var fileDescriptor_6039342a2ba47b72 = []byte{
- // 847 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xdd, 0x6e, 0xdb, 0x36,
- 0x14, 0xae, 0x12, 0x25, 0xb6, 0x8e, 0x62, 0x57, 0x65, 0x52, 0x54, 0x5d, 0x11, 0xcc, 0x10, 0xd6,
- 0x21, 0x17, 0xab, 0x5b, 0x78, 0x45, 0x50, 0x18, 0xc5, 0x80, 0xc4, 0x31, 0x8a, 0x2e, 0xb0, 0x5d,
- 0x28, 0x71, 0x57, 0x6c, 0x17, 0x02, 0x23, 0xd1, 0x8d, 0x3a, 0x4b, 0x14, 0x48, 0xaa, 0x98, 0x1f,
- 0x62, 0x0f, 0xb9, 0x8b, 0xbd, 0xc7, 0xc0, 0x43, 0xc9, 0x51, 0x00, 0x0f, 0x09, 0x7a, 0x47, 0x9d,
- 0xef, 0x87, 0xdf, 0xa1, 0xc4, 0x23, 0xe8, 0x64, 0x4c, 0x89, 0x34, 0x96, 0xfd, 0x42, 0x70, 0xc5,
- 0xc9, 0xbe, 0xe4, 0x3c, 0xff, 0x1c, 0x5d, 0x95, 0xe9, 0x32, 0x89, 0x2a, 0x28, 0xf8, 0xc7, 0x01,
- 0x77, 0x62, 0xd6, 0xa7, 0x54, 0x32, 0xf2, 0x0a, 0x0e, 0x0c, 0x21, 0xa1, 0x8a, 0x45, 0x2a, 0xcd,
- 0x98, 0x54, 0x34, 0x2b, 0x7c, 0xab, 0x67, 0x1d, 0x6d, 0x87, 0x04, 0xb1, 0x33, 0xaa, 0xd8, 0x65,
- 0x8d, 0x90, 0xa7, 0xd0, 0x36, 0x8a, 0x34, 0xf1, 0xb7, 0x7a, 0xd6, 0x91, 0x13, 0xb6, 0xf0, 0xf9,
- 0x7d, 0x42, 0x86, 0xf0, 0xb4, 0x58, 0x52, 0xb5, 0xe0, 0x22, 0x8b, 0xbe, 0x32, 0x21, 0x53, 0x9e,
- 0x47, 0x31, 0x4f, 0x58, 0x4e, 0x33, 0xe6, 0x6f, 0x23, 0xf7, 0x49, 0x4d, 0xf8, 0x68, 0xf0, 0x51,
- 0x05, 0x93, 0xe7, 0xd0, 0x55, 0x54, 0x7c, 0x66, 0x2a, 0x2a, 0x04, 0x4f, 0xca, 0x58, 0xf9, 0x36,
- 0x0a, 0x3a, 0xa6, 0xfa, 0xc1, 0x14, 0x49, 0x02, 0x07, 0x15, 0xcd, 0x84, 0xf8, 0x4a, 0x45, 0x4a,
- 0x73, 0xe5, 0xef, 0xf4, 0xac, 0xa3, 0xee, 0xe0, 0x45, 0x7f, 0x43, 0xcf, 0xfd, 0x46, 0xbf, 0xfd,
- 0x53, 0x8d, 0x7c, 0x34, 0xa2, 0xe1, 0xf6, 0x78, 0xfa, 0x2e, 0x24, 0xc6, 0xaf, 0x09, 0x90, 0x19,
- 0xb8, 0xd5, 0x2e, 0x54, 0xc4, 0xd7, 0xfe, 0x2e, 0x9a, 0x3f, 0xbf, 0xd3, 0xfc, 0x44, 0xc4, 0xd7,
- 0xc3, 0xd6, 0x7c, 0x7a, 0x3e, 0x9d, 0xfd, 0x36, 0x0d, 0xc1, 0x58, 0xe8, 0x22, 0xe9, 0xc3, 0x7e,
- 0xc3, 0x70, 0x9d, 0xba, 0x85, 0x2d, 0x3e, 0xba, 0x21, 0xd6, 0x01, 0x7e, 0x82, 0x2a, 0x56, 0x14,
- 0x17, 0xe5, 0x9a, 0xde, 0x46, 0xba, 0x67, 0x90, 0x51, 0x51, 0xd6, 0xec, 0x73, 0x70, 0xae, 0xb9,
- 0xac, 0xc2, 0x3a, 0xdf, 0x14, 0xb6, 0xad, 0x0d, 0x30, 0x6a, 0x08, 0x1d, 0x34, 0x1b, 0xe4, 0x89,
- 0x31, 0x84, 0x6f, 0x32, 0x74, 0xb5, 0xc9, 0x20, 0x4f, 0xd0, 0xf3, 0x09, 0xb4, 0xd0, 0x93, 0x4b,
- 0xdf, 0xc5, 0x1e, 0x76, 0xf5, 0xe3, 0x4c, 0x92, 0xa0, 0xda, 0x8c, 0xcb, 0x88, 0xfd, 0xa5, 0x04,
- 0xf5, 0xf7, 0x10, 0x76, 0x0d, 0x3c, 0xd6, 0xa5, 0x35, 0x27, 0x16, 0x5c, 0x4a, 0x6d, 0xd1, 0xb9,
- 0xe1, 0x8c, 0x74, 0x6d, 0x26, 0xc9, 0x8f, 0xf0, 0xb0, 0xc1, 0xc1, 0xd8, 0x5d, 0xf3, 0xf9, 0xac,
- 0x59, 0x18, 0xe4, 0x05, 0xec, 0x37, 0x78, 0xeb, 0x16, 0x1f, 0x9a, 0x83, 0x5d, 0x73, 0x1b, 0xb9,
- 0x79, 0xa9, 0xa2, 0x24, 0x15, 0xbe, 0x67, 0x72, 0xf3, 0x52, 0x9d, 0xa5, 0x82, 0xfc, 0x02, 0xae,
- 0x64, 0xaa, 0x2c, 0x22, 0xc5, 0xf9, 0x52, 0xfa, 0x8f, 0x7a, 0xdb, 0x47, 0xee, 0xe0, 0x70, 0xe3,
- 0x11, 0x7d, 0x60, 0x62, 0xf1, 0x3e, 0x5f, 0xf0, 0x10, 0x50, 0x71, 0xa9, 0x05, 0x64, 0x08, 0xce,
- 0x9f, 0x54, 0xa5, 0x91, 0x28, 0x73, 0xe9, 0x93, 0xfb, 0xa8, 0xdb, 0x9a, 0x1f, 0x96, 0xb9, 0x24,
- 0x6f, 0x01, 0x0c, 0x13, 0xc5, 0xfb, 0xf7, 0x11, 0x3b, 0x88, 0xd6, 0xea, 0x3c, 0xcd, 0xbf, 0x50,
- 0xa3, 0x3e, 0xb8, 0x97, 0x1a, 0x05, 0xa8, 0xfe, 0x19, 0x76, 0x14, 0x57, 0x74, 0xe9, 0x3f, 0xee,
- 0x59, 0x77, 0x0b, 0x0d, 0x37, 0x78, 0x05, 0x7b, 0xb7, 0x6e, 0x57, 0x1b, 0xec, 0xf9, 0xc5, 0x38,
- 0xf4, 0x1e, 0x90, 0x0e, 0x38, 0x7a, 0x75, 0x36, 0x3e, 0x9d, 0xbf, 0xf3, 0x2c, 0xd2, 0x02, 0x7d,
- 0x23, 0xbd, 0xad, 0xe0, 0x2d, 0xd8, 0x78, 0xfe, 0x2e, 0xd4, 0xdf, 0x93, 0xf7, 0x40, 0xa3, 0x27,
- 0xe1, 0xc4, 0xb3, 0x88, 0x03, 0x3b, 0x27, 0xe1, 0xe4, 0xf8, 0xb5, 0xb7, 0xa5, 0x6b, 0x9f, 0xde,
- 0x1c, 0x7b, 0xdb, 0x04, 0x60, 0xf7, 0xd3, 0x9b, 0xe3, 0xe8, 0xf8, 0xb5, 0x67, 0x07, 0x7f, 0x5b,
- 0xd0, 0xae, 0x33, 0x10, 0x02, 0x76, 0xc2, 0x64, 0x8c, 0x03, 0xcd, 0x09, 0x71, 0xad, 0x6b, 0x38,
- 0x92, 0xcc, 0xf8, 0xc2, 0x35, 0x39, 0x04, 0x90, 0x8a, 0x0a, 0x85, 0x33, 0x10, 0x87, 0x95, 0x1d,
- 0x3a, 0x58, 0xd1, 0xa3, 0x8f, 0x3c, 0x03, 0x47, 0x30, 0xba, 0x34, 0xa8, 0x8d, 0x68, 0x5b, 0x17,
- 0x10, 0x3c, 0x04, 0xc8, 0x58, 0xc6, 0xc5, 0x2a, 0x2a, 0x25, 0xc3, 0x51, 0x64, 0x87, 0x8e, 0xa9,
- 0xcc, 0x25, 0x0b, 0xfe, 0xb5, 0xa0, 0x3b, 0xe1, 0x49, 0xb9, 0x64, 0x97, 0xab, 0x82, 0x61, 0xaa,
- 0x3f, 0x60, 0xcf, 0x9c, 0x99, 0x5c, 0x49, 0xc5, 0x32, 0x4c, 0xd7, 0x1d, 0xbc, 0xdc, 0x7c, 0xc7,
- 0x6e, 0x49, 0xcd, 0x04, 0xbb, 0x40, 0x59, 0xe3, 0xb6, 0x5d, 0xdd, 0x54, 0xc9, 0xf7, 0xe0, 0x66,
- 0xa8, 0x89, 0xd4, 0xaa, 0xa8, 0xbb, 0x84, 0x6c, 0x6d, 0x43, 0x7e, 0x80, 0x6e, 0x5e, 0x66, 0x11,
- 0x5f, 0x44, 0xa6, 0x28, 0xb1, 0xdf, 0x4e, 0xb8, 0x97, 0x97, 0xd9, 0x6c, 0x61, 0xf6, 0x93, 0xc1,
- 0x4b, 0x70, 0x1b, 0x7b, 0xdd, 0x7e, 0x17, 0x0e, 0xec, 0x5c, 0xcc, 0x66, 0x53, 0xfd, 0xd2, 0xda,
- 0x60, 0x4f, 0x4e, 0xce, 0xc7, 0xde, 0x56, 0xb0, 0x84, 0xef, 0x46, 0x22, 0x55, 0x69, 0x4c, 0x97,
- 0x73, 0xc9, 0xc4, 0xaf, 0xbc, 0x14, 0x39, 0x5b, 0x55, 0x23, 0x62, 0x7d, 0xe8, 0x56, 0xe3, 0xd0,
- 0x87, 0xd0, 0xaa, 0xba, 0xc4, 0x94, 0xee, 0xa0, 0x77, 0xd7, 0x94, 0x09, 0x6b, 0x41, 0x70, 0x05,
- 0xcf, 0x36, 0xec, 0x26, 0xeb, 0xed, 0x46, 0x60, 0xc7, 0xe5, 0x17, 0xe9, 0x5b, 0xf8, 0x85, 0x6f,
- 0x3e, 0xd9, 0xff, 0x4f, 0x1b, 0xa2, 0xf8, 0xf4, 0xf1, 0xef, 0xd5, 0x4f, 0xb4, 0x52, 0x44, 0xf8,
- 0x67, 0xfd, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xc4, 0xbd, 0xe2, 0xb1, 0x69, 0x07, 0x00, 0x00,
+ // 924 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xdf, 0x6e, 0xdb, 0x36,
+ 0x17, 0xaf, 0x62, 0x25, 0x96, 0x8e, 0x62, 0x57, 0x65, 0x52, 0x44, 0xfd, 0x8a, 0xe0, 0x33, 0x84,
+ 0x75, 0xc8, 0xc5, 0x9a, 0x16, 0x59, 0x11, 0x14, 0x41, 0x31, 0x20, 0x71, 0x82, 0xa0, 0x0b, 0x6c,
+ 0x17, 0x4c, 0xdc, 0x15, 0xdb, 0x85, 0x20, 0x4b, 0xb4, 0xa3, 0xce, 0x12, 0x0d, 0x92, 0x2a, 0xe6,
+ 0x87, 0xd8, 0x6b, 0xec, 0xcd, 0xf6, 0x1e, 0x03, 0x0f, 0x25, 0x47, 0x01, 0x5c, 0x34, 0xe8, 0x9d,
+ 0x74, 0x7e, 0x7f, 0xf8, 0x3b, 0x24, 0x75, 0x6c, 0xe8, 0xe4, 0x4c, 0x89, 0x2c, 0x91, 0x87, 0x0b,
+ 0xc1, 0x15, 0x27, 0x3b, 0x92, 0xf3, 0x62, 0x16, 0x4d, 0xca, 0x6c, 0x9e, 0x46, 0x15, 0x14, 0xfe,
+ 0x03, 0xe0, 0x0d, 0xcc, 0xf3, 0x59, 0x2c, 0x19, 0x79, 0x0d, 0xbb, 0x86, 0x90, 0xc6, 0x8a, 0x45,
+ 0x2a, 0xcb, 0x99, 0x54, 0x71, 0xbe, 0x08, 0xac, 0x9e, 0x75, 0xd0, 0xa2, 0x04, 0xb1, 0xf3, 0x58,
+ 0xb1, 0x9b, 0x1a, 0x21, 0xcf, 0xc0, 0x31, 0x8a, 0x2c, 0x0d, 0x36, 0x7a, 0xd6, 0x81, 0x4b, 0xdb,
+ 0xf8, 0xfe, 0x3e, 0x25, 0x27, 0xf0, 0x6c, 0x31, 0x8f, 0xd5, 0x94, 0x8b, 0x3c, 0xfa, 0xc2, 0x84,
+ 0xcc, 0x78, 0x11, 0x25, 0x3c, 0x65, 0x45, 0x9c, 0xb3, 0xa0, 0x85, 0xdc, 0xbd, 0x9a, 0xf0, 0xd1,
+ 0xe0, 0xfd, 0x0a, 0x26, 0x2f, 0xa0, 0xab, 0x62, 0x31, 0x63, 0x2a, 0x5a, 0x08, 0x9e, 0x96, 0x89,
+ 0x0a, 0x6c, 0x14, 0x74, 0x4c, 0xf5, 0x83, 0x29, 0x92, 0x14, 0x76, 0x2b, 0x9a, 0x09, 0xf1, 0x25,
+ 0x16, 0x59, 0x5c, 0xa8, 0x60, 0xb3, 0x67, 0x1d, 0x74, 0x8f, 0x5e, 0x1e, 0xae, 0xe9, 0xf9, 0xb0,
+ 0xd1, 0xef, 0xe1, 0x99, 0x46, 0x3e, 0x1a, 0xd1, 0x49, 0xeb, 0x62, 0x78, 0x49, 0x89, 0xf1, 0x6b,
+ 0x02, 0x64, 0x04, 0x5e, 0xb5, 0x4a, 0x2c, 0x92, 0xdb, 0x60, 0x0b, 0xcd, 0x5f, 0x7c, 0xd3, 0xfc,
+ 0x54, 0x24, 0xb7, 0x27, 0xed, 0xf1, 0xf0, 0x6a, 0x38, 0xfa, 0x6d, 0x48, 0xc1, 0x58, 0xe8, 0x22,
+ 0x39, 0x84, 0x9d, 0x86, 0xe1, 0x2a, 0x75, 0x1b, 0x5b, 0x7c, 0x72, 0x47, 0xac, 0x03, 0xfc, 0x04,
+ 0x55, 0xac, 0x28, 0x59, 0x94, 0x2b, 0xba, 0x83, 0x74, 0xdf, 0x20, 0xfd, 0x45, 0x59, 0xb3, 0xaf,
+ 0xc0, 0xbd, 0xe5, 0xb2, 0x0a, 0xeb, 0x7e, 0x57, 0x58, 0x47, 0x1b, 0x60, 0x54, 0x0a, 0x1d, 0x34,
+ 0x3b, 0x2a, 0x52, 0x63, 0x08, 0xdf, 0x65, 0xe8, 0x69, 0x93, 0xa3, 0x22, 0x45, 0xcf, 0x3d, 0x68,
+ 0xa3, 0x27, 0x97, 0x81, 0x87, 0x3d, 0x6c, 0xe9, 0xd7, 0x91, 0x24, 0x61, 0xb5, 0x18, 0x97, 0x11,
+ 0xfb, 0x4b, 0x89, 0x38, 0xd8, 0x46, 0xd8, 0x33, 0xf0, 0x85, 0x2e, 0xad, 0x38, 0x89, 0xe0, 0x52,
+ 0x6a, 0x8b, 0xce, 0x1d, 0xa7, 0xaf, 0x6b, 0x23, 0x49, 0x7e, 0x84, 0xc7, 0x0d, 0x0e, 0xc6, 0xee,
+ 0x9a, 0xeb, 0xb3, 0x62, 0x61, 0x90, 0x97, 0xb0, 0xd3, 0xe0, 0xad, 0x5a, 0x7c, 0x6c, 0x36, 0x76,
+ 0xc5, 0x6d, 0xe4, 0xe6, 0xa5, 0x8a, 0xd2, 0x4c, 0x04, 0xbe, 0xc9, 0xcd, 0x4b, 0x75, 0x9e, 0x09,
+ 0xf2, 0x0b, 0x78, 0x92, 0xa9, 0x72, 0x11, 0x29, 0xce, 0xe7, 0x32, 0x78, 0xd2, 0x6b, 0x1d, 0x78,
+ 0x47, 0xfb, 0x6b, 0xb7, 0xe8, 0x03, 0x13, 0xd3, 0xf7, 0xc5, 0x94, 0x53, 0x40, 0xc5, 0x8d, 0x16,
+ 0x90, 0x13, 0x70, 0xff, 0x8c, 0x55, 0x16, 0x89, 0xb2, 0x90, 0x01, 0x79, 0x88, 0xda, 0xd1, 0x7c,
+ 0x5a, 0x16, 0x92, 0xbc, 0x03, 0x30, 0x4c, 0x14, 0xef, 0x3c, 0x44, 0xec, 0x22, 0x5a, 0xab, 0x8b,
+ 0xac, 0xf8, 0x1c, 0x1b, 0xf5, 0xee, 0x83, 0xd4, 0x28, 0x40, 0xf5, 0xcf, 0xb0, 0xa9, 0xb8, 0x8a,
+ 0xe7, 0xc1, 0xd3, 0x9e, 0xf5, 0x6d, 0xa1, 0xe1, 0x92, 0x3e, 0x6c, 0x1b, 0x42, 0xc2, 0x8b, 0x69,
+ 0x36, 0x0b, 0xf6, 0x50, 0xdb, 0x5b, 0xab, 0xc5, 0xcf, 0xb0, 0x8f, 0x3c, 0xea, 0x4d, 0xee, 0x5e,
+ 0xc2, 0xd7, 0xb0, 0x7d, 0xef, 0x13, 0x75, 0xc0, 0x1e, 0x5f, 0x5f, 0x50, 0xff, 0x11, 0xe9, 0x80,
+ 0xab, 0x9f, 0xce, 0x2f, 0xce, 0xc6, 0x97, 0xbe, 0x45, 0xda, 0xa0, 0x3f, 0x6b, 0x7f, 0x23, 0x7c,
+ 0x07, 0x36, 0x1e, 0xa2, 0x07, 0xf5, 0xa5, 0xf4, 0x1f, 0x69, 0xf4, 0x94, 0x0e, 0x7c, 0x8b, 0xb8,
+ 0xb0, 0x79, 0x4a, 0x07, 0xc7, 0x6f, 0xfc, 0x0d, 0x5d, 0xfb, 0xf4, 0xf6, 0xd8, 0x6f, 0x11, 0x80,
+ 0xad, 0x4f, 0x6f, 0x8f, 0xa3, 0xe3, 0x37, 0xbe, 0x1d, 0xce, 0xc0, 0x6b, 0x64, 0xd1, 0x53, 0xaf,
+ 0x94, 0x2c, 0x9a, 0xf1, 0x3c, 0xc6, 0xd9, 0xe8, 0xd0, 0x76, 0x29, 0xd9, 0x25, 0xcf, 0x63, 0x7d,
+ 0x49, 0x34, 0x24, 0x26, 0x0c, 0xe7, 0xa1, 0x43, 0xb7, 0x4a, 0xc9, 0xe8, 0x84, 0x91, 0x1f, 0xa0,
+ 0x3b, 0xe5, 0x22, 0x61, 0xd1, 0x4a, 0xd9, 0x42, 0x7c, 0x1b, 0xab, 0x63, 0x23, 0x0f, 0xff, 0xb6,
+ 0xc0, 0xa9, 0x77, 0x8c, 0x10, 0xb0, 0x53, 0x26, 0x13, 0x5c, 0xc2, 0xa5, 0xf8, 0xac, 0x6b, 0x38,
+ 0x40, 0xcd, 0xb0, 0xc5, 0x67, 0xb2, 0x0f, 0x20, 0x55, 0x2c, 0x14, 0x4e, 0x6c, 0xb4, 0xb5, 0xa9,
+ 0x8b, 0x15, 0x3d, 0xa8, 0xc9, 0x73, 0x70, 0x05, 0x8b, 0xe7, 0x06, 0xb5, 0x11, 0x75, 0x74, 0x01,
+ 0xc1, 0x7d, 0x80, 0x9c, 0xe5, 0x5c, 0x2c, 0x75, 0x2e, 0x1c, 0x9c, 0x36, 0x75, 0x4d, 0x65, 0x2c,
+ 0x59, 0xf8, 0xaf, 0x05, 0xdd, 0x01, 0x4f, 0xcb, 0x39, 0xbb, 0x59, 0x2e, 0x18, 0xa6, 0xfa, 0xa3,
+ 0x3e, 0x40, 0xb9, 0x94, 0x8a, 0xe5, 0x98, 0xae, 0x7b, 0xf4, 0x6a, 0xfd, 0x44, 0xb8, 0x27, 0x35,
+ 0xe7, 0x79, 0x8d, 0xb2, 0xc6, 0x6c, 0x98, 0xdc, 0x55, 0xc9, 0xff, 0xc1, 0xcb, 0x51, 0x13, 0xa9,
+ 0xe5, 0xa2, 0xee, 0x12, 0xf2, 0x95, 0x8d, 0xde, 0xc6, 0xa2, 0xcc, 0x23, 0x3e, 0x8d, 0x4c, 0x51,
+ 0x62, 0xbf, 0x1d, 0xba, 0x5d, 0x94, 0xf9, 0x68, 0x6a, 0xd6, 0x93, 0xe1, 0xab, 0xea, 0xbc, 0x2a,
+ 0xd7, 0x7b, 0x87, 0xee, 0xc2, 0xe6, 0xf5, 0x68, 0x34, 0xd4, 0xb7, 0xc3, 0x01, 0x7b, 0x70, 0x7a,
+ 0x75, 0xe1, 0x6f, 0x84, 0x73, 0xf8, 0x5f, 0x5f, 0x64, 0x2a, 0x4b, 0xe2, 0xf9, 0x58, 0x32, 0xf1,
+ 0x2b, 0x2f, 0x45, 0xc1, 0x96, 0xd5, 0x40, 0x5b, 0x6d, 0xba, 0xd5, 0xd8, 0xf4, 0x13, 0x68, 0x57,
+ 0x5d, 0x62, 0xca, 0xaf, 0x5d, 0xe1, 0xc6, 0x4c, 0xa4, 0xb5, 0x20, 0x9c, 0xc0, 0xf3, 0x35, 0xab,
+ 0xc9, 0x7a, 0xb9, 0x3e, 0xd8, 0x49, 0xf9, 0x59, 0x06, 0x16, 0x7e, 0x8f, 0xeb, 0x77, 0xf6, 0xeb,
+ 0x69, 0x29, 0x8a, 0xcf, 0x9e, 0xfe, 0x5e, 0xfd, 0xe4, 0x57, 0x8a, 0x08, 0xff, 0x07, 0xfc, 0x17,
+ 0x00, 0x00, 0xff, 0xff, 0xdd, 0xe8, 0xec, 0xe5, 0x17, 0x08, 0x00, 0x00,
}
diff --git a/ui/metrics/metrics_proto/metrics.proto b/ui/metrics/metrics_proto/metrics.proto
index 194aa6b..08f7d44 100644
--- a/ui/metrics/metrics_proto/metrics.proto
+++ b/ui/metrics/metrics_proto/metrics.proto
@@ -92,6 +92,16 @@
// The metrics for the whole build
optional PerfInfo total = 21;
+
+ optional BuildConfig build_config = 23;
+}
+
+message BuildConfig {
+ optional bool use_goma = 1;
+
+ optional bool use_rbe = 2;
+
+ optional bool force_use_goma = 3;
}
message PerfInfo {
diff --git a/ui/metrics/time.go b/ui/metrics/time.go
index b8baf16..4016563 100644
--- a/ui/metrics/time.go
+++ b/ui/metrics/time.go
@@ -19,13 +19,18 @@
"android/soong/ui/metrics/metrics_proto"
"android/soong/ui/tracer"
+ "github.com/golang/protobuf/proto"
)
+// for testing purpose only
+var _now = now
+
type timeEvent struct {
desc string
name string
- atNanos uint64 // timestamp measured in nanoseconds since the reference date
+ // the time that the event started to occur.
+ start time.Time
}
type TimeTracer interface {
@@ -39,33 +44,26 @@
var _ TimeTracer = &timeTracerImpl{}
-func (t *timeTracerImpl) now() uint64 {
- return uint64(time.Now().UnixNano())
+func now() time.Time {
+ return time.Now()
}
-func (t *timeTracerImpl) Begin(name, desc string, thread tracer.Thread) {
- t.beginAt(name, desc, t.now())
+func (t *timeTracerImpl) Begin(name, desc string, _ tracer.Thread) {
+ t.activeEvents = append(t.activeEvents, timeEvent{name: name, desc: desc, start: _now()})
}
-func (t *timeTracerImpl) beginAt(name, desc string, atNanos uint64) {
- t.activeEvents = append(t.activeEvents, timeEvent{name: name, desc: desc, atNanos: atNanos})
-}
-
-func (t *timeTracerImpl) End(thread tracer.Thread) soong_metrics_proto.PerfInfo {
- return t.endAt(t.now())
-}
-
-func (t *timeTracerImpl) endAt(atNanos uint64) soong_metrics_proto.PerfInfo {
+func (t *timeTracerImpl) End(tracer.Thread) soong_metrics_proto.PerfInfo {
if len(t.activeEvents) < 1 {
panic("Internal error: No pending events for endAt to end!")
}
lastEvent := t.activeEvents[len(t.activeEvents)-1]
t.activeEvents = t.activeEvents[:len(t.activeEvents)-1]
- realTime := atNanos - lastEvent.atNanos
+ realTime := uint64(_now().Sub(lastEvent.start).Nanoseconds())
return soong_metrics_proto.PerfInfo{
- Desc: &lastEvent.desc,
- Name: &lastEvent.name,
- StartTime: &lastEvent.atNanos,
- RealTime: &realTime}
+ Desc: proto.String(lastEvent.desc),
+ Name: proto.String(lastEvent.name),
+ StartTime: proto.Uint64(uint64(lastEvent.start.UnixNano())),
+ RealTime: proto.Uint64(realTime),
+ }
}
diff --git a/ui/metrics/time_test.go b/ui/metrics/time_test.go
new file mode 100644
index 0000000..d73080a
--- /dev/null
+++ b/ui/metrics/time_test.go
@@ -0,0 +1,42 @@
+// Copyright 2020 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package metrics
+
+import (
+ "testing"
+ "time"
+
+ "android/soong/ui/tracer"
+)
+
+func TestEnd(t *testing.T) {
+ startTime := time.Date(2020, time.July, 13, 13, 0, 0, 0, time.UTC)
+ dur := time.Nanosecond * 10
+ initialNow := _now
+ _now = func() time.Time { return startTime.Add(dur) }
+ defer func() { _now = initialNow }()
+
+ timeTracer := &timeTracerImpl{}
+ timeTracer.activeEvents = append(timeTracer.activeEvents, timeEvent{
+ desc: "test",
+ name: "test",
+ start: startTime,
+ })
+
+ perf := timeTracer.End(tracer.Thread(0))
+ if perf.GetRealTime() != uint64(dur.Nanoseconds()) {
+ t.Errorf("got %d, want %d nanoseconds for event duration", perf.GetRealTime(), dur.Nanoseconds())
+ }
+}
diff --git a/ui/metrics/upload_proto/regen.sh b/ui/metrics/upload_proto/regen.sh
new file mode 100755
index 0000000..4521df7
--- /dev/null
+++ b/ui/metrics/upload_proto/regen.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+# Generates the golang source file of upload.proto file.
+
+set -e
+
+function die() { echo "ERROR: $1" >&2; exit 1; }
+
+readonly error_msg="Maybe you need to run 'lunch aosp_arm-eng && m aprotoc blueprint_tools'?"
+
+if ! hash aprotoc &>/dev/null; then
+ die "could not find aprotoc. ${error_msg}"
+fi
+
+if ! aprotoc --go_out=paths=source_relative:. upload.proto; then
+ die "build failed. ${error_msg}"
+fi
diff --git a/ui/metrics/upload_proto/upload.pb.go b/ui/metrics/upload_proto/upload.pb.go
new file mode 100644
index 0000000..614d4c7
--- /dev/null
+++ b/ui/metrics/upload_proto/upload.pb.go
@@ -0,0 +1,134 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: upload.proto
+
+package soong_metrics_upload_proto
+
+import (
+ fmt "fmt"
+ proto "github.com/golang/protobuf/proto"
+ math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type Upload struct {
+ // The timestamp in milliseconds that the build was created.
+ CreationTimestampMs *uint64 `protobuf:"varint,1,opt,name=creation_timestamp_ms,json=creationTimestampMs" json:"creation_timestamp_ms,omitempty"`
+ // The timestamp in milliseconds when the build was completed.
+ CompletionTimestampMs *uint64 `protobuf:"varint,2,opt,name=completion_timestamp_ms,json=completionTimestampMs" json:"completion_timestamp_ms,omitempty"`
+ // The branch name.
+ BranchName *string `protobuf:"bytes,3,opt,name=branch_name,json=branchName" json:"branch_name,omitempty"`
+ // The target name.
+ TargetName *string `protobuf:"bytes,4,opt,name=target_name,json=targetName" json:"target_name,omitempty"`
+ // A list of metrics filepaths to upload.
+ MetricsFiles []string `protobuf:"bytes,5,rep,name=metrics_files,json=metricsFiles" json:"metrics_files,omitempty"`
+ // A list of directories to delete after the copy of metrics files
+ // is completed for uploading.
+ DirectoriesToDelete []string `protobuf:"bytes,6,rep,name=directories_to_delete,json=directoriesToDelete" json:"directories_to_delete,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Upload) Reset() { *m = Upload{} }
+func (m *Upload) String() string { return proto.CompactTextString(m) }
+func (*Upload) ProtoMessage() {}
+func (*Upload) Descriptor() ([]byte, []int) {
+ return fileDescriptor_91b94b655bd2a7e5, []int{0}
+}
+
+func (m *Upload) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Upload.Unmarshal(m, b)
+}
+func (m *Upload) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Upload.Marshal(b, m, deterministic)
+}
+func (m *Upload) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Upload.Merge(m, src)
+}
+func (m *Upload) XXX_Size() int {
+ return xxx_messageInfo_Upload.Size(m)
+}
+func (m *Upload) XXX_DiscardUnknown() {
+ xxx_messageInfo_Upload.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Upload proto.InternalMessageInfo
+
+func (m *Upload) GetCreationTimestampMs() uint64 {
+ if m != nil && m.CreationTimestampMs != nil {
+ return *m.CreationTimestampMs
+ }
+ return 0
+}
+
+func (m *Upload) GetCompletionTimestampMs() uint64 {
+ if m != nil && m.CompletionTimestampMs != nil {
+ return *m.CompletionTimestampMs
+ }
+ return 0
+}
+
+func (m *Upload) GetBranchName() string {
+ if m != nil && m.BranchName != nil {
+ return *m.BranchName
+ }
+ return ""
+}
+
+func (m *Upload) GetTargetName() string {
+ if m != nil && m.TargetName != nil {
+ return *m.TargetName
+ }
+ return ""
+}
+
+func (m *Upload) GetMetricsFiles() []string {
+ if m != nil {
+ return m.MetricsFiles
+ }
+ return nil
+}
+
+func (m *Upload) GetDirectoriesToDelete() []string {
+ if m != nil {
+ return m.DirectoriesToDelete
+ }
+ return nil
+}
+
+func init() {
+ proto.RegisterType((*Upload)(nil), "soong_metrics_upload.Upload")
+}
+
+func init() {
+ proto.RegisterFile("upload.proto", fileDescriptor_91b94b655bd2a7e5)
+}
+
+var fileDescriptor_91b94b655bd2a7e5 = []byte{
+ // 230 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0xb1, 0x4a, 0x04, 0x31,
+ 0x10, 0x86, 0xd9, 0xbb, 0xf3, 0xe0, 0xe2, 0xd9, 0xec, 0x79, 0x18, 0x44, 0x70, 0xd1, 0x66, 0x2b,
+ 0x0b, 0x0b, 0x1f, 0x40, 0xc4, 0x4e, 0x8b, 0xe5, 0x6c, 0x6c, 0x86, 0x98, 0x1d, 0xd7, 0x40, 0x92,
+ 0x09, 0xc9, 0xf8, 0x1c, 0xbe, 0xb2, 0x6c, 0xe2, 0xe2, 0x82, 0x76, 0xc3, 0xff, 0x7d, 0x7f, 0x31,
+ 0xbf, 0xd8, 0x7e, 0x06, 0x4b, 0xaa, 0xbf, 0x09, 0x91, 0x98, 0xea, 0xd3, 0x44, 0xe4, 0x07, 0x70,
+ 0xc8, 0xd1, 0xe8, 0x04, 0x85, 0x5d, 0x7d, 0x2d, 0xc4, 0xfa, 0x25, 0x9f, 0xf5, 0xad, 0xd8, 0xeb,
+ 0x88, 0x8a, 0x0d, 0x79, 0x60, 0xe3, 0x30, 0xb1, 0x72, 0x01, 0x5c, 0x92, 0x55, 0x53, 0xb5, 0xab,
+ 0x6e, 0x37, 0xc1, 0xc3, 0xc4, 0x9e, 0x52, 0x7d, 0x27, 0xce, 0x34, 0xb9, 0x60, 0xf1, 0x6f, 0x6b,
+ 0x91, 0x5b, 0xfb, 0x5f, 0x3c, 0xef, 0x5d, 0x8a, 0xe3, 0xb7, 0xa8, 0xbc, 0xfe, 0x00, 0xaf, 0x1c,
+ 0xca, 0x65, 0x53, 0xb5, 0x9b, 0x4e, 0x94, 0xe8, 0x59, 0x39, 0x1c, 0x05, 0x56, 0x71, 0x40, 0x2e,
+ 0xc2, 0xaa, 0x08, 0x25, 0xca, 0xc2, 0xb5, 0x38, 0x99, 0x5e, 0x79, 0x37, 0x16, 0x93, 0x3c, 0x6a,
+ 0x96, 0xed, 0xa6, 0xdb, 0xfe, 0x84, 0x8f, 0x63, 0x36, 0xbe, 0xd4, 0x9b, 0x88, 0x9a, 0x29, 0x1a,
+ 0x4c, 0xc0, 0x04, 0x3d, 0x5a, 0x64, 0x94, 0xeb, 0x2c, 0xef, 0x66, 0xf0, 0x40, 0x0f, 0x19, 0xdd,
+ 0x5f, 0xbc, 0x9e, 0xff, 0xb7, 0x14, 0xe4, 0x15, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x64, 0x04,
+ 0xa8, 0xf4, 0x54, 0x01, 0x00, 0x00,
+}
diff --git a/ui/metrics/upload_proto/upload.proto b/ui/metrics/upload_proto/upload.proto
new file mode 100644
index 0000000..bcd0ab2
--- /dev/null
+++ b/ui/metrics/upload_proto/upload.proto
@@ -0,0 +1,39 @@
+// Copyright 2020 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto2";
+
+package soong_metrics_upload;
+option go_package = "soong_metrics_upload_proto";
+
+message Upload {
+ // The timestamp in milliseconds that the build was created.
+ optional uint64 creation_timestamp_ms = 1;
+
+ // The timestamp in milliseconds when the build was completed.
+ optional uint64 completion_timestamp_ms = 2;
+
+ // The branch name.
+ optional string branch_name = 3;
+
+ // The target name.
+ optional string target_name = 4;
+
+ // A list of metrics filepaths to upload.
+ repeated string metrics_files = 5;
+
+ // A list of directories to delete after the copy of metrics files
+ // is completed for uploading.
+ repeated string directories_to_delete = 6;
+}