diff options
57 files changed, 1365 insertions, 291 deletions
diff --git a/android/arch.go b/android/arch.go index f505ec653..616ceaddb 100644 --- a/android/arch.go +++ b/android/arch.go @@ -1717,7 +1717,7 @@ func getNdkAbisConfig() []archConfig { func getAmlAbisConfig() []archConfig { return []archConfig{ - {"arm", "armv7-a", "", []string{"armeabi-v7a"}}, + {"arm", "armv7-a-neon", "", []string{"armeabi-v7a"}}, {"arm64", "armv8-a", "", []string{"arm64-v8a"}}, {"x86", "", "", []string{"x86"}}, {"x86_64", "", "", []string{"x86_64"}}, diff --git a/android/defs.go b/android/defs.go index 83daa0368..2b1bd85c9 100644 --- a/android/defs.go +++ b/android/defs.go @@ -69,8 +69,9 @@ var ( // A symlink rule. Symlink = pctx.AndroidStaticRule("Symlink", blueprint.RuleParams{ - Command: "rm -f $out && ln -f -s $fromPath $out", - Description: "symlink $out", + Command: "rm -f $out && ln -f -s $fromPath $out", + Description: "symlink $out", + SymlinkOutputs: []string{"$out"}, }, "fromPath") diff --git a/android/makefile_goal.go b/android/makefile_goal.go index eae3976a8..b5d9d691e 100644 --- a/android/makefile_goal.go +++ b/android/makefile_goal.go @@ -93,7 +93,6 @@ func (p *makefileGoal) AndroidMkEntries() []AndroidMkEntries { func MakefileGoalFactory() Module { module := &makefileGoal{} module.AddProperties(&module.properties) - // This module is device-only - InitAndroidArchModule(module, DeviceSupported, MultilibFirst) + InitAndroidModule(module) return module } diff --git a/android/module.go b/android/module.go index 822e5bdf9..70a343e47 100644 --- a/android/module.go +++ b/android/module.go @@ -43,6 +43,8 @@ type BuildParams struct { Description string Output WritablePath Outputs WritablePaths + SymlinkOutput WritablePath + SymlinkOutputs WritablePaths ImplicitOutput WritablePath ImplicitOutputs WritablePaths Input Path @@ -1763,6 +1765,27 @@ func (m *moduleContext) ModuleBuild(pctx PackageContext, params ModuleBuildParam m.Build(pctx, BuildParams(params)) } +func validateBuildParams(params blueprint.BuildParams) error { + // Validate that the symlink outputs are declared outputs or implicit outputs + allOutputs := map[string]bool{} + for _, output := range params.Outputs { + allOutputs[output] = true + } + for _, output := range params.ImplicitOutputs { + allOutputs[output] = true + } + for _, symlinkOutput := range params.SymlinkOutputs { + if !allOutputs[symlinkOutput] { + return fmt.Errorf( + "Symlink output %s is not a declared output or implicit output", + symlinkOutput) + } + } + return nil +} + +// Convert build parameters from their concrete Android types into their string representations, +// and combine the singular and plural fields of the same type (e.g. Output and Outputs). func convertBuildParams(params BuildParams) blueprint.BuildParams { bparams := blueprint.BuildParams{ Rule: params.Rule, @@ -1770,6 +1793,7 @@ func convertBuildParams(params BuildParams) blueprint.BuildParams { Deps: params.Deps, Outputs: params.Outputs.Strings(), ImplicitOutputs: params.ImplicitOutputs.Strings(), + SymlinkOutputs: params.SymlinkOutputs.Strings(), Inputs: params.Inputs.Strings(), Implicits: params.Implicits.Strings(), OrderOnly: params.OrderOnly.Strings(), @@ -1784,6 +1808,9 @@ func convertBuildParams(params BuildParams) blueprint.BuildParams { if params.Output != nil { bparams.Outputs = append(bparams.Outputs, params.Output.String()) } + if params.SymlinkOutput != nil { + bparams.SymlinkOutputs = append(bparams.SymlinkOutputs, params.SymlinkOutput.String()) + } if params.ImplicitOutput != nil { bparams.ImplicitOutputs = append(bparams.ImplicitOutputs, params.ImplicitOutput.String()) } @@ -1799,6 +1826,7 @@ func convertBuildParams(params BuildParams) blueprint.BuildParams { bparams.Outputs = proptools.NinjaEscapeList(bparams.Outputs) bparams.ImplicitOutputs = proptools.NinjaEscapeList(bparams.ImplicitOutputs) + bparams.SymlinkOutputs = proptools.NinjaEscapeList(bparams.SymlinkOutputs) bparams.Inputs = proptools.NinjaEscapeList(bparams.Inputs) bparams.Implicits = proptools.NinjaEscapeList(bparams.Implicits) bparams.OrderOnly = proptools.NinjaEscapeList(bparams.OrderOnly) @@ -1855,7 +1883,15 @@ func (m *moduleContext) Build(pctx PackageContext, params BuildParams) { m.buildParams = append(m.buildParams, params) } - m.bp.Build(pctx.PackageContext, convertBuildParams(params)) + bparams := convertBuildParams(params) + err := validateBuildParams(bparams) + if err != nil { + m.ModuleErrorf( + "%s: build parameter validation failed: %s", + m.ModuleName(), + err.Error()) + } + m.bp.Build(pctx.PackageContext, bparams) } func (m *moduleContext) Phony(name string, deps ...Path) { diff --git a/android/module_test.go b/android/module_test.go index 6e648d7bb..3a039e29a 100644 --- a/android/module_test.go +++ b/android/module_test.go @@ -187,3 +187,49 @@ func TestErrorDependsOnDisabledModule(t *testing.T) { _, errs = ctx.PrepareBuildActions(config) FailIfNoMatchingErrors(t, `module "foo": depends on disabled module "bar"`, errs) } + +func TestValidateCorrectBuildParams(t *testing.T) { + config := TestConfig(buildDir, nil, "", nil) + pathContext := PathContextForTesting(config) + bparams := convertBuildParams(BuildParams{ + // Test with Output + Output: PathForOutput(pathContext, "undeclared_symlink"), + SymlinkOutput: PathForOutput(pathContext, "undeclared_symlink"), + }) + + err := validateBuildParams(bparams) + if err != nil { + t.Error(err) + } + + bparams = convertBuildParams(BuildParams{ + // Test with ImplicitOutput + ImplicitOutput: PathForOutput(pathContext, "undeclared_symlink"), + SymlinkOutput: PathForOutput(pathContext, "undeclared_symlink"), + }) + + err = validateBuildParams(bparams) + if err != nil { + t.Error(err) + } +} + +func TestValidateIncorrectBuildParams(t *testing.T) { + config := TestConfig(buildDir, nil, "", nil) + pathContext := PathContextForTesting(config) + params := BuildParams{ + Output: PathForOutput(pathContext, "regular_output"), + Outputs: PathsForOutput(pathContext, []string{"out1", "out2"}), + ImplicitOutput: PathForOutput(pathContext, "implicit_output"), + ImplicitOutputs: PathsForOutput(pathContext, []string{"i_out1", "_out2"}), + SymlinkOutput: PathForOutput(pathContext, "undeclared_symlink"), + } + + bparams := convertBuildParams(params) + err := validateBuildParams(bparams) + if err != nil { + FailIfNoMatchingErrors(t, "undeclared_symlink is not a declared output or implicit output", []error{err}) + } else { + t.Errorf("Expected build params to fail validation: %+v", bparams) + } +} diff --git a/android/rule_builder.go b/android/rule_builder.go index afb5f4e4a..8dc9d6a42 100644 --- a/android/rule_builder.go +++ b/android/rule_builder.go @@ -246,6 +246,41 @@ func (r *RuleBuilder) Outputs() WritablePaths { return outputList } +func (r *RuleBuilder) symlinkOutputSet() map[string]WritablePath { + symlinkOutputs := make(map[string]WritablePath) + for _, c := range r.commands { + for _, symlinkOutput := range c.symlinkOutputs { + symlinkOutputs[symlinkOutput.String()] = symlinkOutput + } + } + return symlinkOutputs +} + +// SymlinkOutputs returns the list of paths that the executor (Ninja) would +// verify, after build edge completion, that: +// +// 1) Created output symlinks match the list of paths in this list exactly (no more, no fewer) +// 2) Created output files are *not* declared in this list. +// +// These symlink outputs are expected to be a subset of outputs or implicit +// outputs, or they would fail validation at build param construction time +// later, to support other non-rule-builder approaches for constructing +// statements. +func (r *RuleBuilder) SymlinkOutputs() WritablePaths { + symlinkOutputs := r.symlinkOutputSet() + + var symlinkOutputList WritablePaths + for _, symlinkOutput := range symlinkOutputs { + symlinkOutputList = append(symlinkOutputList, symlinkOutput) + } + + sort.Slice(symlinkOutputList, func(i, j int) bool { + return symlinkOutputList[i].String() < symlinkOutputList[j].String() + }) + + return symlinkOutputList +} + func (r *RuleBuilder) depFileSet() map[string]WritablePath { depFiles := make(map[string]WritablePath) for _, c := range r.commands { @@ -467,6 +502,7 @@ func (r *RuleBuilder) Build(pctx PackageContext, ctx BuilderContext, name string Implicits: r.Inputs(), Output: output, ImplicitOutputs: implicitOutputs, + SymlinkOutputs: r.SymlinkOutputs(), Depfile: depFile, Deps: depFormat, Description: desc, @@ -478,14 +514,15 @@ func (r *RuleBuilder) Build(pctx PackageContext, ctx BuilderContext, name string // RuleBuilderCommand, so they can be used chained or unchained. All methods that add text implicitly add a single // space as a separator from the previous method. type RuleBuilderCommand struct { - buf strings.Builder - inputs Paths - implicits Paths - orderOnlys Paths - outputs WritablePaths - depFiles WritablePaths - tools Paths - rspFileInputs Paths + buf strings.Builder + inputs Paths + implicits Paths + orderOnlys Paths + outputs WritablePaths + symlinkOutputs WritablePaths + depFiles WritablePaths + tools Paths + rspFileInputs Paths // spans [start,end) of the command that should not be ninja escaped unescapedSpans [][2]int @@ -715,6 +752,40 @@ func (c *RuleBuilderCommand) ImplicitOutputs(paths WritablePaths) *RuleBuilderCo return c } +// ImplicitSymlinkOutput declares the specified path as an implicit output that +// will be a symlink instead of a regular file. Does not modify the command +// line. +func (c *RuleBuilderCommand) ImplicitSymlinkOutput(path WritablePath) *RuleBuilderCommand { + c.symlinkOutputs = append(c.symlinkOutputs, path) + return c.ImplicitOutput(path) +} + +// ImplicitSymlinkOutputs declares the specified paths as implicit outputs that +// will be a symlinks instead of regular files. Does not modify the command +// line. +func (c *RuleBuilderCommand) ImplicitSymlinkOutputs(paths WritablePaths) *RuleBuilderCommand { + for _, path := range paths { + c.ImplicitSymlinkOutput(path) + } + return c +} + +// SymlinkOutput declares the specified path as an output that will be a symlink +// instead of a regular file. Modifies the command line. +func (c *RuleBuilderCommand) SymlinkOutput(path WritablePath) *RuleBuilderCommand { + c.symlinkOutputs = append(c.symlinkOutputs, path) + return c.Output(path) +} + +// SymlinkOutputsl declares the specified paths as outputs that will be symlinks +// instead of regular files. Modifies the command line. +func (c *RuleBuilderCommand) SymlinkOutputs(paths WritablePaths) *RuleBuilderCommand { + for _, path := range paths { + c.SymlinkOutput(path) + } + return c +} + // ImplicitDepFile adds the specified depfile path to the paths returned by RuleBuilder.DepFiles without modifying // the command line, and causes RuleBuilder.Build file to set the depfile flag for ninja. If multiple depfiles // are added to commands in a single RuleBuilder then RuleBuilder.Build will add an extra command to merge the diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go index c41b06734..0d1070da2 100644 --- a/android/rule_builder_test.go +++ b/android/rule_builder_test.go @@ -35,6 +35,7 @@ func pathContext() PathContext { "a": nil, "b": nil, "ls": nil, + "ln": nil, "turbine": nil, "java": nil, "javac": nil, @@ -67,6 +68,32 @@ func ExampleRuleBuilder() { // outputs: ["out/linked"] } +func ExampleRuleBuilder_SymlinkOutputs() { + rule := NewRuleBuilder() + + ctx := pathContext() + + rule.Command(). + Tool(PathForSource(ctx, "ln")). + FlagWithInput("-s ", PathForTesting("a.o")). + SymlinkOutput(PathForOutput(ctx, "a")) + rule.Command().Text("cp out/a out/b"). + ImplicitSymlinkOutput(PathForOutput(ctx, "b")) + + fmt.Printf("commands: %q\n", strings.Join(rule.Commands(), " && ")) + fmt.Printf("tools: %q\n", rule.Tools()) + fmt.Printf("inputs: %q\n", rule.Inputs()) + fmt.Printf("outputs: %q\n", rule.Outputs()) + fmt.Printf("symlink_outputs: %q\n", rule.SymlinkOutputs()) + + // Output: + // commands: "ln -s a.o out/a && cp out/a out/b" + // tools: ["ln"] + // inputs: ["a.o"] + // outputs: ["out/a" "out/b"] + // symlink_outputs: ["out/a" "out/b"] +} + func ExampleRuleBuilder_Temporary() { rule := NewRuleBuilder() @@ -293,6 +320,8 @@ func TestRuleBuilder(t *testing.T) { Input(PathForSource(ctx, "Input")). Output(PathForOutput(ctx, "Output")). OrderOnly(PathForSource(ctx, "OrderOnly")). + SymlinkOutput(PathForOutput(ctx, "SymlinkOutput")). + ImplicitSymlinkOutput(PathForOutput(ctx, "ImplicitSymlinkOutput")). Text("Text"). Tool(PathForSource(ctx, "Tool")) @@ -318,17 +347,18 @@ func TestRuleBuilder(t *testing.T) { } wantInputs := PathsForSource(ctx, []string{"Implicit", "Input", "input", "input2", "input3"}) - wantOutputs := PathsForOutput(ctx, []string{"ImplicitOutput", "Output", "output", "output2", "output3"}) + wantOutputs := PathsForOutput(ctx, []string{"ImplicitOutput", "ImplicitSymlinkOutput", "Output", "SymlinkOutput", "output", "output2", "output3"}) wantDepFiles := PathsForOutput(ctx, []string{"DepFile", "depfile", "ImplicitDepFile", "depfile2"}) wantTools := PathsForSource(ctx, []string{"Tool", "tool2"}) wantOrderOnlys := PathsForSource(ctx, []string{"OrderOnly", "OrderOnlys"}) + wantSymlinkOutputs := PathsForOutput(ctx, []string{"ImplicitSymlinkOutput", "SymlinkOutput"}) t.Run("normal", func(t *testing.T) { rule := NewRuleBuilder() addCommands(rule) wantCommands := []string{ - "out/DepFile Flag FlagWithArg=arg FlagWithDepFile=out/depfile FlagWithInput=input FlagWithOutput=out/output Input out/Output Text Tool after command2 old cmd", + "out/DepFile Flag FlagWithArg=arg FlagWithDepFile=out/depfile FlagWithInput=input FlagWithOutput=out/output Input out/Output out/SymlinkOutput Text Tool after command2 old cmd", "command2 out/depfile2 input2 out/output2 tool2", "command3 input3 out/output2 out/output3", } @@ -345,6 +375,9 @@ func TestRuleBuilder(t *testing.T) { if g, w := rule.Outputs(), wantOutputs; !reflect.DeepEqual(w, g) { t.Errorf("\nwant rule.Outputs() = %#v\n got %#v", w, g) } + if g, w := rule.SymlinkOutputs(), wantSymlinkOutputs; !reflect.DeepEqual(w, g) { + t.Errorf("\nwant rule.SymlinkOutputs() = %#v\n got %#v", w, g) + } if g, w := rule.DepFiles(), wantDepFiles; !reflect.DeepEqual(w, g) { t.Errorf("\nwant rule.DepFiles() = %#v\n got %#v", w, g) } @@ -365,7 +398,7 @@ func TestRuleBuilder(t *testing.T) { addCommands(rule) wantCommands := []string{ - "__SBOX_OUT_DIR__/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_OUT_DIR__/depfile FlagWithInput=input FlagWithOutput=__SBOX_OUT_DIR__/output Input __SBOX_OUT_DIR__/Output Text Tool after command2 old cmd", + "__SBOX_OUT_DIR__/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_OUT_DIR__/depfile FlagWithInput=input FlagWithOutput=__SBOX_OUT_DIR__/output Input __SBOX_OUT_DIR__/Output __SBOX_OUT_DIR__/SymlinkOutput Text Tool after command2 old cmd", "command2 __SBOX_OUT_DIR__/depfile2 input2 __SBOX_OUT_DIR__/output2 tool2", "command3 input3 __SBOX_OUT_DIR__/output2 __SBOX_OUT_DIR__/output3", } diff --git a/android/singleton.go b/android/singleton.go index 9832378d5..bb6614dad 100644 --- a/android/singleton.go +++ b/android/singleton.go @@ -168,6 +168,10 @@ func (s *singletonContextAdaptor) Build(pctx PackageContext, params BuildParams) s.buildParams = append(s.buildParams, params) } bparams := convertBuildParams(params) + err := validateBuildParams(bparams) + if err != nil { + s.Errorf("%s: build parameter validation failed: %s", s.Name(), err.Error()) + } s.SingletonContext.Build(pctx.PackageContext, bparams) } diff --git a/android/variable.go b/android/variable.go index a9495ccbe..73062ed64 100644 --- a/android/variable.go +++ b/android/variable.go @@ -90,6 +90,11 @@ type variableProperties struct { Required []string Host_required []string Target_required []string + Strip struct { + All *bool + Keep_symbols *bool + Keep_symbols_and_debug_frame *bool + } } // eng is true for -eng builds, and can be used to turn on additionaly heavyweight debugging diff --git a/android/visibility.go b/android/visibility.go index 51d561120..7eac47166 100644 --- a/android/visibility.go +++ b/android/visibility.go @@ -351,7 +351,10 @@ func parseRules(ctx BaseModuleContext, currentPkg, property string, visibility [ case "__subpackages__": r = subpackagesRule{pkg} default: - continue + ctx.PropertyErrorf(property, "invalid visibility pattern %q. Must match "+ + " //<package>:<scope>, //<package> or :<scope> "+ + "where <scope> is one of \"__pkg__\", \"__subpackages__\"", + v) } } @@ -397,7 +400,8 @@ func splitRule(ctx BaseModuleContext, ruleExpression string, currentPkg, propert // ensure all the rules on this module are checked. ctx.PropertyErrorf(property, "invalid visibility pattern %q must match"+ - " //<package>:<module>, //<package> or :<module>", + " //<package>:<scope>, //<package> or :<scope> "+ + "where <scope> is one of \"__pkg__\", \"__subpackages__\"", ruleExpression) return false, "", "" } @@ -443,7 +447,7 @@ func visibilityRuleEnforcer(ctx TopDownMutatorContext) { rule := effectiveVisibilityRules(ctx.Config(), depQualified) if !rule.matches(qualified) { - ctx.ModuleErrorf("depends on %s which is not visible to this module", depQualified) + ctx.ModuleErrorf("depends on %s which is not visible to this module\nYou may need to add %q to its visibility", depQualified, "//"+ctx.ModuleDir()) } }) } diff --git a/android/visibility_test.go b/android/visibility_test.go index 9d9e57438..cb5ef35b3 100644 --- a/android/visibility_test.go +++ b/android/visibility_test.go @@ -731,7 +731,7 @@ var visibilityTests = []struct { }`), }, expectedErrors: []string{ - `module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module`, + `module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module\nYou may need to add "//namespace" to its visibility`, }, }, { @@ -760,7 +760,7 @@ var visibilityTests = []struct { }`), }, expectedErrors: []string{ - `module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module`, + `module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module\nYou may need to add "//namespace" to its visibility`, }, }, { diff --git a/apex/allowed_deps.txt b/apex/allowed_deps.txt index cd4b05616..07e78afb4 100644 --- a/apex/allowed_deps.txt +++ b/apex/allowed_deps.txt @@ -154,7 +154,9 @@ crtend_android(minSdkVersion:apex_inherit) crtend_so(minSdkVersion:16) crtend_so(minSdkVersion:apex_inherit) datastallprotosnano(minSdkVersion:29) +derive_sdk(minSdkVersion:30) derive_sdk(minSdkVersion:current) +derive_sdk_prefer32(minSdkVersion:30) derive_sdk_prefer32(minSdkVersion:current) dnsresolver_aidl_interface-unstable-ndk_platform(minSdkVersion:29) DocumentsUI-res-lib(minSdkVersion:29) @@ -165,6 +167,7 @@ ExtServices-core(minSdkVersion:current) flatbuffer_headers(minSdkVersion:(no version)) fmtlib(minSdkVersion:29) framework-permission(minSdkVersion:current) +framework-sdkextensions(minSdkVersion:30) framework-sdkextensions(minSdkVersion:current) framework-statsd(minSdkVersion:current) framework-tethering(minSdkVersion:current) diff --git a/apex/builder.go b/apex/builder.go index 7c125ef4f..ad673d656 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -21,6 +21,7 @@ import ( "path/filepath" "runtime" "sort" + "strconv" "strings" "android/soong/android" @@ -552,14 +553,16 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { optFlags = append(optFlags, "--android_manifest "+androidManifestFile.String()) } - targetSdkVersion := ctx.Config().DefaultAppTargetSdk(ctx).String() - // TODO(b/157078772): propagate min_sdk_version to apexer. - minSdkVersion := ctx.Config().DefaultAppTargetSdk(ctx).String() - moduleMinSdkVersion := a.minSdkVersion(ctx) - if moduleMinSdkVersion.EqualTo(android.SdkVersion_Android10) { - minSdkVersion = moduleMinSdkVersion.String() + minSdkVersion := moduleMinSdkVersion.String() + + // bundletool doesn't understand what "current" is. We need to transform it to codename + if moduleMinSdkVersion.IsCurrent() { + minSdkVersion = ctx.Config().DefaultAppTargetSdk(ctx).String() } + // apex module doesn't have a concept of target_sdk_version, hence for the time being + // targetSdkVersion == default targetSdkVersion of the branch. + targetSdkVersion := strconv.Itoa(ctx.Config().DefaultAppTargetSdk(ctx).FinalOrFutureInt()) if java.UseApiFingerprint(ctx) { targetSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", java.ApiFingerprintPath(ctx).String()) diff --git a/cc/androidmk.go b/cc/androidmk.go index e58a172b8..5c5505385 100644 --- a/cc/androidmk.go +++ b/cc/androidmk.go @@ -482,12 +482,6 @@ func (c *vndkPrebuiltLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, en entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) { c.libraryDecorator.androidMkWriteExportedFlags(entries) - path, file := filepath.Split(c.path.ToMakePath().String()) - stem, suffix, ext := android.SplitFileExt(file) - entries.SetString("LOCAL_BUILT_MODULE_STEM", "$(LOCAL_MODULE)"+ext) - entries.SetString("LOCAL_MODULE_SUFFIX", suffix) - entries.SetString("LOCAL_MODULE_PATH", path) - entries.SetString("LOCAL_MODULE_STEM", stem) if c.tocFile.Valid() { entries.SetString("LOCAL_SOONG_TOC", c.tocFile.String()) } diff --git a/cc/builder.go b/cc/builder.go index 8c8aa1754..81c09b1a1 100644 --- a/cc/builder.go +++ b/cc/builder.go @@ -44,14 +44,14 @@ var ( blueprint.RuleParams{ Depfile: "${out}.d", Deps: blueprint.DepsGCC, - Command: "${config.CcWrapper}$ccCmd -c $cFlags -MD -MF ${out}.d -o $out $in", + Command: "$relPwd ${config.CcWrapper}$ccCmd -c $cFlags -MD -MF ${out}.d -o $out $in", CommandDeps: []string{"$ccCmd"}, }, "ccCmd", "cFlags") ccNoDeps = pctx.AndroidStaticRule("ccNoDeps", blueprint.RuleParams{ - Command: "$ccCmd -c $cFlags -o $out $in", + Command: "$relPwd $ccCmd -c $cFlags -o $out $in", CommandDeps: []string{"$ccCmd"}, }, "ccCmd", "cFlags") @@ -220,7 +220,7 @@ var ( Labels: map[string]string{"type": "abi-dump", "tool": "header-abi-dumper"}, ExecStrategy: "${config.REAbiDumperExecStrategy}", Platform: map[string]string{ - remoteexec.PoolKey: "${config.RECXXPool}", + remoteexec.PoolKey: "${config.RECXXPool}", }, }, []string{"cFlags", "exportDirs"}, nil) @@ -84,6 +84,7 @@ func RegisterCCBuildComponents(ctx android.RegistrationContext) { ctx.TopDown("lto_deps", ltoDepsMutator) ctx.BottomUp("lto", ltoMutator).Parallel() + ctx.BottomUp("check_linktype", checkLinkTypeMutator).Parallel() ctx.TopDown("double_loadable", checkDoubleLoadableLibraries).Parallel() }) @@ -2004,7 +2005,7 @@ func BeginMutator(ctx android.BottomUpMutatorContext) { // Whether a module can link to another module, taking into // account NDK linking. -func checkLinkType(ctx android.ModuleContext, from LinkableInterface, to LinkableInterface, +func checkLinkType(ctx android.BaseModuleContext, from LinkableInterface, to LinkableInterface, tag blueprint.DependencyTag) { switch t := tag.(type) { @@ -2124,6 +2125,18 @@ func checkLinkType(ctx android.ModuleContext, from LinkableInterface, to Linkabl } } +func checkLinkTypeMutator(ctx android.BottomUpMutatorContext) { + if c, ok := ctx.Module().(*Module); ok { + ctx.VisitDirectDeps(func(dep android.Module) { + depTag := ctx.OtherModuleDependencyTag(dep) + ccDep, ok := dep.(LinkableInterface) + if ok { + checkLinkType(ctx, c, ccDep, depTag) + } + }) + } +} + // Tests whether the dependent library is okay to be double loaded inside a single process. // If a library has a vendor variant and is a (transitive) dependency of an LLNDK library, // it is subject to be double loaded. Such lib should be explicitly marked as double_loadable: true @@ -2132,15 +2145,15 @@ func checkDoubleLoadableLibraries(ctx android.TopDownMutatorContext) { check := func(child, parent android.Module) bool { to, ok := child.(*Module) if !ok { - // follow thru cc.Defaults, etc. - return true + return false } if lib, ok := to.linker.(*libraryDecorator); !ok || !lib.shared() { return false } - // if target lib has no vendor variant, keep checking dependency graph + // Even if target lib has no vendor variant, keep checking dependency graph + // in case it depends on vendor_available but not double_loadable transtively. if !to.HasVendorVariant() { return true } @@ -2304,8 +2317,6 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { return } - checkLinkType(ctx, c, ccDep, depTag) - linkFile := ccDep.OutputFile() if libDepTag, ok := depTag.(libraryDependencyTag); ok { diff --git a/cc/cc_test.go b/cc/cc_test.go index d1780cd70..5951fb3d5 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -103,6 +103,7 @@ func testCcErrorWithConfig(t *testing.T, pattern string, config android.Config) } func testCcError(t *testing.T, pattern string, bp string) { + t.Helper() config := TestConfig(buildDir, android.Android, nil, bp, nil) config.TestProductVariables.DeviceVndkVersion = StringPtr("current") config.TestProductVariables.Platform_vndk_version = StringPtr("VER") @@ -111,6 +112,7 @@ func testCcError(t *testing.T, pattern string, bp string) { } func testCcErrorProductVndk(t *testing.T, pattern string, bp string) { + t.Helper() config := TestConfig(buildDir, android.Android, nil, bp, nil) config.TestProductVariables.DeviceVndkVersion = StringPtr("current") config.TestProductVariables.ProductVndkVersion = StringPtr("current") @@ -388,10 +390,12 @@ func TestVndk(t *testing.T) { ctx := testCcWithConfig(t, config) - checkVndkModule(t, ctx, "libvndk", "vndk-VER", false, "", vendorVariant) - checkVndkModule(t, ctx, "libvndk_private", "vndk-VER", false, "", vendorVariant) - checkVndkModule(t, ctx, "libvndk_sp", "vndk-sp-VER", true, "", vendorVariant) - checkVndkModule(t, ctx, "libvndk_sp_private", "vndk-sp-VER", true, "", vendorVariant) + // subdir == "" because VNDK libs are not supposed to be installed separately. + // They are installed as part of VNDK APEX instead. + checkVndkModule(t, ctx, "libvndk", "", false, "", vendorVariant) + checkVndkModule(t, ctx, "libvndk_private", "", false, "", vendorVariant) + checkVndkModule(t, ctx, "libvndk_sp", "", true, "", vendorVariant) + checkVndkModule(t, ctx, "libvndk_sp_private", "", true, "", vendorVariant) // Check VNDK snapshot output. @@ -1123,6 +1127,7 @@ func TestVendorSnapshotUse(t *testing.T) { arch: { arm64: { srcs: ["libvndk.so"], + export_include_dirs: ["include/libvndk"], }, }, } @@ -1149,6 +1154,7 @@ func TestVendorSnapshotUse(t *testing.T) { shared_libs: ["libvndk"], static_libs: ["libvendor", "libvendor_without_snapshot"], compile_multilib: "64", + srcs: ["client.cpp"], } cc_binary { @@ -1160,6 +1166,7 @@ func TestVendorSnapshotUse(t *testing.T) { system_shared_libs: [], static_libs: ["libvndk"], compile_multilib: "64", + srcs: ["bin.cpp"], } vendor_snapshot_static { @@ -1170,6 +1177,7 @@ func TestVendorSnapshotUse(t *testing.T) { arch: { arm64: { src: "libvndk.a", + export_include_dirs: ["include/libvndk"], }, }, } @@ -1182,6 +1190,7 @@ func TestVendorSnapshotUse(t *testing.T) { arch: { arm64: { src: "libvendor.so", + export_include_dirs: ["include/libvendor"], }, }, } @@ -1194,6 +1203,7 @@ func TestVendorSnapshotUse(t *testing.T) { arch: { arm64: { src: "libvendor.a", + export_include_dirs: ["include/libvendor"], }, }, } @@ -1213,15 +1223,20 @@ func TestVendorSnapshotUse(t *testing.T) { depsBp := GatherRequiredDepsForTest(android.Android) mockFS := map[string][]byte{ - "deps/Android.bp": []byte(depsBp), - "framework/Android.bp": []byte(frameworkBp), - "vendor/Android.bp": []byte(vendorProprietaryBp), - "vendor/libvndk.a": nil, - "vendor/libvendor.a": nil, - "vendor/libvendor.so": nil, - "vendor/bin": nil, - "vndk/Android.bp": []byte(vndkBp), - "vndk/libvndk.so": nil, + "deps/Android.bp": []byte(depsBp), + "framework/Android.bp": []byte(frameworkBp), + "vendor/Android.bp": []byte(vendorProprietaryBp), + "vendor/bin": nil, + "vendor/bin.cpp": nil, + "vendor/client.cpp": nil, + "vendor/include/libvndk/a.h": nil, + "vendor/include/libvendor/b.h": nil, + "vendor/libvndk.a": nil, + "vendor/libvendor.a": nil, + "vendor/libvendor.so": nil, + "vndk/Android.bp": []byte(vndkBp), + "vndk/include/libvndk/a.h": nil, + "vndk/libvndk.so": nil, } config := TestConfig(buildDir, android.Android, nil, "", mockFS) @@ -1240,27 +1255,41 @@ func TestVendorSnapshotUse(t *testing.T) { binaryVariant := "android_vendor.BOARD_arm64_armv8-a" // libclient uses libvndk.vndk.BOARD.arm64, libvendor.vendor_static.BOARD.arm64, libvendor_without_snapshot - libclientLdRule := ctx.ModuleForTests("libclient", sharedVariant).Rule("ld") - libclientFlags := libclientLdRule.Args["libFlags"] + libclientCcFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("cc").Args["cFlags"] + for _, includeFlags := range []string{ + "-Ivndk/include/libvndk", // libvndk + "-Ivendor/include/libvendor", // libvendor + } { + if !strings.Contains(libclientCcFlags, includeFlags) { + t.Errorf("flags for libclient must contain %#v, but was %#v.", + includeFlags, libclientCcFlags) + } + } + libclientLdFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("ld").Args["libFlags"] for _, input := range [][]string{ []string{sharedVariant, "libvndk.vndk.BOARD.arm64"}, []string{staticVariant, "libvendor.vendor_static.BOARD.arm64"}, []string{staticVariant, "libvendor_without_snapshot"}, } { outputPaths := getOutputPaths(ctx, input[0] /* variant */, []string{input[1]} /* module name */) - if !strings.Contains(libclientFlags, outputPaths[0].String()) { - t.Errorf("libflags for libclient must contain %#v, but was %#v", outputPaths[0], libclientFlags) + if !strings.Contains(libclientLdFlags, outputPaths[0].String()) { + t.Errorf("libflags for libclient must contain %#v, but was %#v", outputPaths[0], libclientLdFlags) } } // bin_without_snapshot uses libvndk.vendor_static.BOARD.arm64 - binWithoutSnapshotLdRule := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("ld") - binWithoutSnapshotFlags := binWithoutSnapshotLdRule.Args["libFlags"] + binWithoutSnapshotCcFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("cc").Args["cFlags"] + if !strings.Contains(binWithoutSnapshotCcFlags, "-Ivendor/include/libvndk") { + t.Errorf("flags for bin_without_snapshot must contain %#v, but was %#v.", + "-Ivendor/include/libvndk", binWithoutSnapshotCcFlags) + } + + binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("ld").Args["libFlags"] libVndkStaticOutputPaths := getOutputPaths(ctx, staticVariant, []string{"libvndk.vendor_static.BOARD.arm64"}) - if !strings.Contains(binWithoutSnapshotFlags, libVndkStaticOutputPaths[0].String()) { + if !strings.Contains(binWithoutSnapshotLdFlags, libVndkStaticOutputPaths[0].String()) { t.Errorf("libflags for bin_without_snapshot must contain %#v, but was %#v", - libVndkStaticOutputPaths[0], binWithoutSnapshotFlags) + libVndkStaticOutputPaths[0], binWithoutSnapshotLdFlags) } // libvendor.so is installed by libvendor.vendor_shared.BOARD.arm64 @@ -1637,6 +1666,35 @@ func TestDoubleLoadableDepError(t *testing.T) { `) } +func TestCheckVndkMembershipBeforeDoubleLoadable(t *testing.T) { + testCcError(t, "module \"libvndksp\" variant .*: .*: VNDK-SP must only depend on VNDK-SP", ` + cc_library { + name: "libvndksp", + shared_libs: ["libanothervndksp"], + vendor_available: true, + vndk: { + enabled: true, + support_system_process: true, + } + } + + cc_library { + name: "libllndk", + shared_libs: ["libanothervndksp"], + } + + llndk_library { + name: "libllndk", + symbol_file: "", + } + + cc_library { + name: "libanothervndksp", + vendor_available: true, + } + `) +} + func TestVndkExt(t *testing.T) { // This test checks the VNDK-Ext properties. bp := ` @@ -2427,8 +2485,8 @@ func TestEnforceProductVndkVersion(t *testing.T) { ctx := testCcWithConfig(t, config) - checkVndkModule(t, ctx, "libvndk", "vndk-VER", false, "", productVariant) - checkVndkModule(t, ctx, "libvndk_sp", "vndk-sp-VER", true, "", productVariant) + checkVndkModule(t, ctx, "libvndk", "", false, "", productVariant) + checkVndkModule(t, ctx, "libvndk_sp", "", true, "", productVariant) } func TestEnforceProductVndkVersionErrors(t *testing.T) { diff --git a/cc/config/global.go b/cc/config/global.go index 1aa262132..a170652c1 100644 --- a/cc/config/global.go +++ b/cc/config/global.go @@ -53,13 +53,6 @@ var ( "-Werror=pragma-pack", "-Werror=pragma-pack-suspicious-include", "-Werror=unreachable-code-loop-increment", - - // -fdebug-compilation-dir=. is used to make both the action command line and the output - // independent of the working directory of the action. - // Using cc1 flags since RBE's input processor does not yet have the updated version - // of LLVM that promotes the cc1 flag to driver level flag. - // See: https://reviews.llvm.org/D63387 - "-Xclang,-fdebug-compilation-dir,.", } commonGlobalConlyflags = []string{} @@ -157,6 +150,10 @@ var ( var pctx = android.NewPackageContext("android/soong/cc/config") func init() { + if android.BuildOs == android.Linux { + commonGlobalCflags = append(commonGlobalCflags, "-fdebug-prefix-map=/proc/self/cwd=") + } + pctx.StaticVariable("CommonGlobalConlyflags", strings.Join(commonGlobalConlyflags, " ")) pctx.StaticVariable("DeviceGlobalCppflags", strings.Join(deviceGlobalCppflags, " ")) pctx.StaticVariable("DeviceGlobalLdflags", strings.Join(deviceGlobalLdflags, " ")) diff --git a/cc/image.go b/cc/image.go index ea6f5675c..6710e94b7 100644 --- a/cc/image.go +++ b/cc/image.go @@ -63,12 +63,12 @@ const ( func (ctx *moduleContext) ProductSpecific() bool { return ctx.ModuleContext.ProductSpecific() || - (ctx.mod.HasVendorVariant() && ctx.mod.inProduct() && !ctx.mod.IsVndk()) + (ctx.mod.HasVendorVariant() && ctx.mod.inProduct()) } func (ctx *moduleContext) SocSpecific() bool { return ctx.ModuleContext.SocSpecific() || - (ctx.mod.HasVendorVariant() && ctx.mod.inVendor() && !ctx.mod.IsVndk()) + (ctx.mod.HasVendorVariant() && ctx.mod.inVendor()) } func (ctx *moduleContextImpl) inProduct() bool { diff --git a/cc/library.go b/cc/library.go index 090abf997..1b7e1ed67 100644 --- a/cc/library.go +++ b/cc/library.go @@ -1246,19 +1246,23 @@ func (library *libraryDecorator) installSymlinkToRuntimeApex(ctx ModuleContext, func (library *libraryDecorator) install(ctx ModuleContext, file android.Path) { if library.shared() { if ctx.Device() && ctx.useVndk() { - if ctx.isVndkSp() { - library.baseInstaller.subDir = "vndk-sp" - } else if ctx.isVndk() { + // set subDir for VNDK extensions + if ctx.isVndkExt() { + if ctx.isVndkSp() { + library.baseInstaller.subDir = "vndk-sp" + } else { + library.baseInstaller.subDir = "vndk" + } + } + + // In some cases we want to use core variant for VNDK-Core libs + if ctx.isVndk() && !ctx.isVndkSp() && !ctx.isVndkExt() { mayUseCoreVariant := true if ctx.mustUseVendorVariant() { mayUseCoreVariant = false } - if ctx.isVndkExt() { - mayUseCoreVariant = false - } - if ctx.Config().CFIEnabledForPath(ctx.ModuleDir()) && ctx.Arch().ArchType == android.Arm64 { mayUseCoreVariant = false } @@ -1269,15 +1273,12 @@ func (library *libraryDecorator) install(ctx ModuleContext, file android.Path) { library.useCoreVariant = true } } - library.baseInstaller.subDir = "vndk" } - // Append a version to vndk or vndk-sp directories on the system partition. + // do not install vndk libs + // vndk libs are packaged into VNDK APEX if ctx.isVndk() && !ctx.isVndkExt() { - vndkVersion := ctx.DeviceConfig().PlatformVndkVersion() - if vndkVersion != "current" && vndkVersion != "" { - library.baseInstaller.subDir += "-" + vndkVersion - } + return } } else if len(library.Properties.Stubs.Versions) > 0 && !ctx.Host() && ctx.directlyInAnyApex() { // Bionic libraries (e.g. libc.so) is installed to the bootstrap subdirectory. diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go index 4c206e6d2..64e3ea8d0 100644 --- a/cc/vendor_snapshot.go +++ b/cc/vendor_snapshot.go @@ -241,6 +241,8 @@ func (p *vendorSnapshotLibraryDecorator) link(ctx ModuleContext, }) } + p.libraryDecorator.flagExporter.setProvider(ctx) + return in } diff --git a/cc/vndk.go b/cc/vndk.go index 981e039ec..89ac503c8 100644 --- a/cc/vndk.go +++ b/cc/vndk.go @@ -129,7 +129,7 @@ func (vndk *vndkdep) typeName() string { return "native:vendor:vndkspext" } -func (vndk *vndkdep) vndkCheckLinkType(ctx android.ModuleContext, to *Module, tag blueprint.DependencyTag) { +func (vndk *vndkdep) vndkCheckLinkType(ctx android.BaseModuleContext, to *Module, tag blueprint.DependencyTag) { if to.linker == nil { return } @@ -540,6 +540,9 @@ func isVndkSnapshotLibrary(config android.DeviceConfig, m *Module, if m.Target().NativeBridge == android.NativeBridgeEnabled { return nil, "", false } + // !inVendor: There's product/vendor variants for VNDK libs. We only care about vendor variants. + // !installable: Snapshot only cares about "installable" modules. + // isSnapshotPrebuilt: Snapshotting a snapshot doesn't make sense. if !m.inVendor() || !m.installable(apexInfo) || m.isSnapshotPrebuilt() { return nil, "", false } diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go index 7c47ef42a..82a7732aa 100644 --- a/cc/vndk_prebuilt.go +++ b/cc/vndk_prebuilt.go @@ -169,6 +169,8 @@ func (p *vndkPrebuiltLibraryDecorator) link(ctx ModuleContext, TableOfContents: p.tocFile, }) + p.libraryDecorator.flagExporter.setProvider(ctx) + return in } @@ -199,21 +201,7 @@ func (p *vndkPrebuiltLibraryDecorator) isSnapshotPrebuilt() bool { } func (p *vndkPrebuiltLibraryDecorator) install(ctx ModuleContext, file android.Path) { - arches := ctx.DeviceConfig().Arches() - if len(arches) == 0 || arches[0].ArchType.String() != p.arch() { - return - } - if ctx.DeviceConfig().BinderBitness() != p.binderBit() { - return - } - if p.shared() { - if ctx.isVndkSp() { - p.baseInstaller.subDir = "vndk-sp-" + p.version() - } else if ctx.isVndk() { - p.baseInstaller.subDir = "vndk-" + p.version() - } - p.baseInstaller.install(ctx, file) - } + // do not install vndk libs } func vndkPrebuiltSharedLibrary() *Module { diff --git a/cmd/soong_build/bazel_overlay.go b/cmd/soong_build/bazel_overlay.go index b149e80d2..cdc5775f9 100644 --- a/cmd/soong_build/bazel_overlay.go +++ b/cmd/soong_build/bazel_overlay.go @@ -31,7 +31,7 @@ import ( const ( // The default `load` preamble for every generated BUILD file. soongModuleLoad = `package(default_visibility = ["//visibility:public"]) -load("//:soong_module.bzl", "soong_module") +load("//build/bazel/overlay_rules:soong_module.bzl", "soong_module") ` @@ -62,7 +62,7 @@ load("//:soong_module.bzl", "soong_module") soongModuleBzl = ` %s -load(":providers.bzl", "SoongModuleInfo") +load("//build/bazel/overlay_rules:providers.bzl", "SoongModuleInfo") def _generic_soong_module_impl(ctx): return [ @@ -396,7 +396,7 @@ func createRuleShims(packages []*bpdoc.Package) (map[string]RuleShim, error) { ruleShims := map[string]RuleShim{} for _, pkg := range packages { - content := "load(\":providers.bzl\", \"SoongModuleInfo\")\n" + content := "load(\"//build/bazel/overlay_rules:providers.bzl\", \"SoongModuleInfo\")\n" bzlFileName := strings.ReplaceAll(pkg.Path, "android/soong/", "") bzlFileName = strings.ReplaceAll(bzlFileName, ".", "_") @@ -452,16 +452,15 @@ func createBazelOverlay(ctx *android.Context, bazelOverlayDir string) error { buildFile.Write([]byte(generateSoongModuleTarget(blueprintCtx, module) + "\n\n")) buildFile.Close() }) + var err error - if err := writeReadOnlyFile(bazelOverlayDir, "WORKSPACE", ""); err != nil { + // Write top level files: WORKSPACE and BUILD. These files are empty. + if err = writeReadOnlyFile(bazelOverlayDir, "WORKSPACE", ""); err != nil { return err } - if err := writeReadOnlyFile(bazelOverlayDir, "BUILD", ""); err != nil { - return err - } - - if err := writeReadOnlyFile(bazelOverlayDir, "providers.bzl", providersBzl); err != nil { + // Used to denote that the top level directory is a package. + if err = writeReadOnlyFile(bazelOverlayDir, "BUILD", ""); err != nil { return err } @@ -474,13 +473,22 @@ func createBazelOverlay(ctx *android.Context, bazelOverlayDir string) error { return err } + // Write .bzl Starlark files into the bazel_rules top level directory (provider and rule definitions) + bazelRulesDir := bazelOverlayDir + "/build/bazel/overlay_rules" + if err = writeReadOnlyFile(bazelRulesDir, "BUILD", ""); err != nil { + return err + } + if err = writeReadOnlyFile(bazelRulesDir, "providers.bzl", providersBzl); err != nil { + return err + } + for bzlFileName, ruleShim := range ruleShims { - if err := writeReadOnlyFile(bazelOverlayDir, bzlFileName+".bzl", ruleShim.content); err != nil { + if err = writeReadOnlyFile(bazelRulesDir, bzlFileName+".bzl", ruleShim.content); err != nil { return err } } - return writeReadOnlyFile(bazelOverlayDir, "soong_module.bzl", generateSoongModuleBzl(ruleShims)) + return writeReadOnlyFile(bazelRulesDir, "soong_module.bzl", generateSoongModuleBzl(ruleShims)) } // Generate the content of soong_module.bzl with the rule shim load statements @@ -489,7 +497,7 @@ func generateSoongModuleBzl(bzlLoads map[string]RuleShim) string { var loadStmts string var moduleRuleMap string for bzlFileName, ruleShim := range bzlLoads { - loadStmt := "load(\"//:" + loadStmt := "load(\"//build/bazel/overlay_rules:" loadStmt += bzlFileName loadStmt += ".bzl\"" for _, rule := range ruleShim.rules { @@ -558,9 +566,7 @@ func generateSoongModuleTarget( func buildFileForModule(ctx *blueprint.Context, module blueprint.Module) (*os.File, error) { // Create nested directories for the BUILD file dirPath := filepath.Join(bazelOverlayDir, packagePath(ctx, module)) - if _, err := os.Stat(dirPath); os.IsNotExist(err) { - os.MkdirAll(dirPath, os.ModePerm) - } + createDirectoryIfNonexistent(dirPath) // Open the file for appending, and create it if it doesn't exist f, err := os.OpenFile( filepath.Join(dirPath, "BUILD.bazel"), @@ -582,10 +588,17 @@ func buildFileForModule(ctx *blueprint.Context, module blueprint.Module) (*os.Fi return f, nil } +func createDirectoryIfNonexistent(dir string) { + if _, err := os.Stat(dir); os.IsNotExist(err) { + os.MkdirAll(dir, os.ModePerm) + } +} + // The overlay directory should be read-only, sufficient for bazel query. The files // are not intended to be edited by end users. func writeReadOnlyFile(dir string, baseName string, content string) error { - pathToFile := filepath.Join(bazelOverlayDir, baseName) + createDirectoryIfNonexistent(dir) + pathToFile := filepath.Join(dir, baseName) // 0444 is read-only return ioutil.WriteFile(pathToFile, []byte(content), 0444) } diff --git a/cmd/soong_build/bazel_overlay_test.go b/cmd/soong_build/bazel_overlay_test.go index f0c851521..de060bbe5 100644 --- a/cmd/soong_build/bazel_overlay_test.go +++ b/cmd/soong_build/bazel_overlay_test.go @@ -362,7 +362,7 @@ func TestGenerateModuleRuleShims(t *testing.T) { } } - expectedBzl := `load(":providers.bzl", "SoongModuleInfo") + expectedBzl := `load("//build/bazel/overlay_rules:providers.bzl", "SoongModuleInfo") def _foo_binary_impl(ctx): return [SoongModuleInfo()] @@ -440,7 +440,7 @@ func TestGenerateSoongModuleBzl(t *testing.T) { } actualSoongModuleBzl := generateSoongModuleBzl(ruleShims) - expectedLoad := "load(\"//:foo.bzl\", \"foo_binary\", \"foo_library\", \"foo_test_\")" + expectedLoad := "load(\"//build/bazel/overlay_rules:foo.bzl\", \"foo_binary\", \"foo_library\", \"foo_test_\")" expectedRuleMap := `soong_module_rule_map = { "foo_binary": foo_binary, "foo_library": foo_library, diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go index 4a8d3cd50..47110c91a 100644 --- a/java/dexpreopt_bootjars_test.go +++ b/java/dexpreopt_bootjars_test.go @@ -87,7 +87,7 @@ func TestDexpreoptBootJars(t *testing.T) { ruleFile := "boot-foo.art" expectedInputs := []string{ - "dex_artjars/android/apex/com.android.art/javalib/arm64/boot.art", + "dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art", "dex_bootjars_input/foo.jar", "dex_bootjars_input/bar.jar", "dex_bootjars_input/baz.jar", diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go index f0d82ff92..0f8888a7d 100644 --- a/java/dexpreopt_config.go +++ b/java/dexpreopt_config.go @@ -89,7 +89,7 @@ func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig { frameworkModules := global.BootJars.CopyOf() frameworkModules.RemoveList(artModules) - artSubdir := "apex/com.android.art/javalib" + artSubdir := "apex/art_boot_images/javalib" frameworkSubdir := "system/framework" // ART config for the primary boot image in the ART apex. diff --git a/linkerconfig/Android.bp b/linkerconfig/Android.bp new file mode 100644 index 000000000..8807a2e68 --- /dev/null +++ b/linkerconfig/Android.bp @@ -0,0 +1,17 @@ +bootstrap_go_package { + name: "soong-linkerconfig", + pkgPath: "android/soong/linkerconfig", + deps: [ + "blueprint", + "soong", + "soong-android", + "soong-etc", + ], + srcs: [ + "linkerconfig.go", + ], + testSrcs: [ + "linkerconfig_test.go", + ], + pluginFor: ["soong_build"], +} diff --git a/linkerconfig/linkerconfig.go b/linkerconfig/linkerconfig.go new file mode 100644 index 000000000..1c44c746f --- /dev/null +++ b/linkerconfig/linkerconfig.go @@ -0,0 +1,108 @@ +// Copyright (C) 2020 The Android Open Source Project +// +// 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 linkerconfig + +import ( + "android/soong/android" + "android/soong/etc" + + "github.com/google/blueprint/proptools" +) + +var ( + pctx = android.NewPackageContext("android/soong/linkerconfig") +) + +func init() { + pctx.HostBinToolVariable("conv_linker_config", "conv_linker_config") + android.RegisterModuleType("linker_config", linkerConfigFactory) +} + +type linkerConfigProperties struct { + // source linker configuration property file + Src *string `android:"path"` + + // If set to true, allow module to be installed to one of the partitions. + // Default value is true. + // Installable should be marked as false for APEX configuration to avoid + // conflicts of configuration on /system/etc directory. + Installable *bool +} + +type linkerConfig struct { + android.ModuleBase + properties linkerConfigProperties + + outputFilePath android.OutputPath + installDirPath android.InstallPath +} + +// Implement PrebuiltEtcModule interface to fit in APEX prebuilt list. +var _ etc.PrebuiltEtcModule = (*linkerConfig)(nil) + +func (l *linkerConfig) BaseDir() string { + return "etc" +} + +func (l *linkerConfig) SubDir() string { + return "" +} + +func (l *linkerConfig) OutputFile() android.OutputPath { + return l.outputFilePath +} + +func (l *linkerConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) { + inputFile := android.PathForModuleSrc(ctx, android.String(l.properties.Src)) + l.outputFilePath = android.PathForModuleOut(ctx, "linker.config.pb").OutputPath + l.installDirPath = android.PathForModuleInstall(ctx, "etc") + linkerConfigRule := android.NewRuleBuilder() + linkerConfigRule.Command(). + BuiltTool(ctx, "conv_linker_config"). + Flag("proto"). + FlagWithInput("-s ", inputFile). + FlagWithOutput("-o ", l.outputFilePath) + linkerConfigRule.Build(pctx, ctx, "conv_linker_config", + "Generate linker config protobuf "+l.outputFilePath.String()) + + if proptools.BoolDefault(l.properties.Installable, true) { + ctx.InstallFile(l.installDirPath, l.outputFilePath.Base(), l.outputFilePath) + } +} + +// linker_config generates protobuf file from json file. This protobuf file will be used from +// linkerconfig while generating ld.config.txt. Format of this file can be found from +// https://android.googlesource.com/platform/system/linkerconfig/+/master/README.md +func linkerConfigFactory() android.Module { + m := &linkerConfig{} + m.AddProperties(&m.properties) + android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibFirst) + return m +} + +func (l *linkerConfig) AndroidMkEntries() []android.AndroidMkEntries { + installable := proptools.BoolDefault(l.properties.Installable, true) + return []android.AndroidMkEntries{android.AndroidMkEntries{ + Class: "ETC", + OutputFile: android.OptionalPathForPath(l.outputFilePath), + ExtraEntries: []android.AndroidMkExtraEntriesFunc{ + func(entries *android.AndroidMkEntries) { + entries.SetString("LOCAL_MODULE_PATH", l.installDirPath.ToMakePath().String()) + entries.SetString("LOCAL_INSTALLED_MODULE_STEM", l.outputFilePath.Base()) + entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !installable) + }, + }, + }} +} diff --git a/linkerconfig/linkerconfig_test.go b/linkerconfig/linkerconfig_test.go new file mode 100644 index 000000000..13c276abf --- /dev/null +++ b/linkerconfig/linkerconfig_test.go @@ -0,0 +1,127 @@ +// Copyright (C) 2020 The Android Open Source Project +// +// 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 linkerconfig + +import ( + "android/soong/android" + "io/ioutil" + "os" + "reflect" + "testing" +) + +var buildDir string + +func setUp() { + var err error + buildDir, err = ioutil.TempDir("", "soong_etc_test") + if err != nil { + panic(err) + } +} + +func tearDown() { + os.RemoveAll(buildDir) +} + +func TestMain(m *testing.M) { + run := func() int { + setUp() + defer tearDown() + + return m.Run() + } + + os.Exit(run()) +} + +func testContext(t *testing.T, bp string) (*android.TestContext, android.Config) { + t.Helper() + + fs := map[string][]byte{ + "linker.config.json": nil, + } + + config := android.TestArchConfig(buildDir, nil, bp, fs) + + ctx := android.NewTestArchContext() + ctx.RegisterModuleType("linker_config", linkerConfigFactory) + ctx.Register(config) + + _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) + android.FailIfErrored(t, errs) + _, errs = ctx.PrepareBuildActions(config) + android.FailIfErrored(t, errs) + + return ctx, config +} + +func TestBaseLinkerConfig(t *testing.T) { + ctx, config := testContext(t, ` + linker_config { + name: "linker-config-base", + src: "linker.config.json", + } + `) + + expected := map[string][]string{ + "LOCAL_MODULE": {"linker-config-base"}, + "LOCAL_MODULE_CLASS": {"ETC"}, + "LOCAL_INSTALLED_MODULE_STEM": {"linker.config.pb"}, + } + + p := ctx.ModuleForTests("linker-config-base", "android_arm64_armv8-a").Module().(*linkerConfig) + + if p.outputFilePath.Base() != "linker.config.pb" { + t.Errorf("expected linker.config.pb, got %q", p.outputFilePath.Base()) + } + + entries := android.AndroidMkEntriesForTest(t, config, "", p)[0] + for k, expectedValue := range expected { + if value, ok := entries.EntryMap[k]; ok { + if !reflect.DeepEqual(value, expectedValue) { + t.Errorf("Value of %s is '%s', but expected as '%s'", k, value, expectedValue) + } + } else { + t.Errorf("%s is not defined", k) + } + } + + if value, ok := entries.EntryMap["LOCAL_UNINSTALLABLE_MODULE"]; ok { + t.Errorf("Value of LOCAL_UNINSTALLABLE_MODULE is %s, but expected as empty", value) + } +} + +func TestUninstallableLinkerConfig(t *testing.T) { + ctx, config := testContext(t, ` + linker_config { + name: "linker-config-base", + src: "linker.config.json", + installable: false, + } + `) + + expected := []string{"true"} + + p := ctx.ModuleForTests("linker-config-base", "android_arm64_armv8-a").Module().(*linkerConfig) + entries := android.AndroidMkEntriesForTest(t, config, "", p)[0] + if value, ok := entries.EntryMap["LOCAL_UNINSTALLABLE_MODULE"]; ok { + if !reflect.DeepEqual(value, expected) { + t.Errorf("LOCAL_UNINSTALLABLE_MODULE is expected to be true but %s", value) + } + } else { + t.Errorf("LOCAL_UNINSTALLABLE_MODULE is not defined") + } +} diff --git a/linkerconfig/proto/Android.bp b/linkerconfig/proto/Android.bp new file mode 100644 index 000000000..c04887e9b --- /dev/null +++ b/linkerconfig/proto/Android.bp @@ -0,0 +1,28 @@ +cc_library_static { + name: "lib_linker_config_proto_lite", + host_supported: true, + recovery_available: true, + proto: { + export_proto_headers: true, + type: "lite", + }, + srcs: ["linker_config.proto"], +} + +python_library_host { + name: "linker_config_proto", + version: { + py2: { + enabled: false, + }, + py3: { + enabled: true, + }, + }, + srcs: [ + "linker_config.proto", + ], + proto: { + canonical_path_from_root: false, + }, +} diff --git a/linkerconfig/proto/OWNERS b/linkerconfig/proto/OWNERS new file mode 100644 index 000000000..31f0460a1 --- /dev/null +++ b/linkerconfig/proto/OWNERS @@ -0,0 +1,3 @@ +kiyoungkim@google.com +jiyong@google.com +jooyung@google.com diff --git a/linkerconfig/proto/linker_config.proto b/linkerconfig/proto/linker_config.proto new file mode 100644 index 000000000..91a596824 --- /dev/null +++ b/linkerconfig/proto/linker_config.proto @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * 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. + */ + +// This format file defines configuration file for linkerconfig. Details on this +// format can be found from +// https://android.googlesource.com/platform/system/linkerconfig/+/master/README.md + +syntax = "proto3"; + +package android.linkerconfig.proto; + +message LinkerConfig { + // Extra permitted paths + repeated string permittedPaths = 1; + + // Force APEX namespace visible + bool visible = 2; +} diff --git a/rust/bindgen.go b/rust/bindgen.go index 68f219e45..3db2d654f 100644 --- a/rust/bindgen.go +++ b/rust/bindgen.go @@ -150,6 +150,18 @@ func (b *bindgenDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) andr esc := proptools.NinjaAndShellEscapeList + // Filter out invalid cflags + for _, flag := range b.ClangProperties.Cflags { + if flag == "-x c++" || flag == "-xc++" { + ctx.PropertyErrorf("cflags", + "-x c++ should not be specified in cflags; setting cpp_std specifies this is a C++ header, or change the file extension to '.hpp' or '.hh'") + } + if strings.HasPrefix(flag, "-std=") { + ctx.PropertyErrorf("cflags", + "-std should not be specified in cflags; instead use c_std or cpp_std") + } + } + // Module defined clang flags and include paths cflags = append(cflags, esc(b.ClangProperties.Cflags)...) for _, include := range b.ClangProperties.Local_include_dirs { diff --git a/rust/bindgen_test.go b/rust/bindgen_test.go index 9cccf13be..c7ce42bb4 100644 --- a/rust/bindgen_test.go +++ b/rust/bindgen_test.go @@ -134,3 +134,29 @@ func TestRustBindgenStdVersions(t *testing.T) { t.Errorf("cpp_std value not passed in to rust_bindgen as a clang flag") } } + +func TestBindgenDisallowedFlags(t *testing.T) { + // Make sure passing '-x c++' to cflags generates an error + testRustError(t, "cflags: -x c\\+\\+ should not be specified in cflags.*", ` + rust_bindgen { + name: "libbad_flag", + wrapper_src: "src/any.h", + crate_name: "bindgen", + stem: "libbindgen", + source_stem: "bindings", + cflags: ["-x c++"] + } + `) + + // Make sure passing '-std=' to cflags generates an error + testRustError(t, "cflags: -std should not be specified in cflags.*", ` + rust_bindgen { + name: "libbad_flag", + wrapper_src: "src/any.h", + crate_name: "bindgen", + stem: "libbindgen", + source_stem: "bindings", + cflags: ["-std=foo"] + } + `) +} diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go index b9a879a20..b5c70dc2c 100644 --- a/rust/config/allowed_list.go +++ b/rust/config/allowed_list.go @@ -6,10 +6,11 @@ var ( // for an example. // TODO(b/160223496): enable rustfmt globally. RustAllowedPaths = []string{ + "external/adhd", + "external/crosvm", "external/minijail", "external/rust", - "external/crosvm", - "external/adhd", + "external/vm_tools/p9", "frameworks/native/libs/binder/rust", "packages/modules/Virtualization", "prebuilts/rust", diff --git a/scripts/Android.bp b/scripts/Android.bp index 7782c6862..92f5c5335 100644 --- a/scripts/Android.bp +++ b/scripts/Android.bp @@ -206,3 +206,22 @@ python_binary_host { "ninja_rsp.py", ], } + +python_binary_host { + name: "conv_linker_config", + srcs: [ + "conv_linker_config.py", + ], + version: { + py2: { + enabled: false, + }, + py3: { + enabled: true, + embedded_launcher: true, + }, + }, + libs: [ + "linker_config_proto", + ], +} diff --git a/scripts/OWNERS b/scripts/OWNERS index 8c644247e..819808362 100644 --- a/scripts/OWNERS +++ b/scripts/OWNERS @@ -2,3 +2,4 @@ per-file system-clang-format,system-clang-format-2 = enh@google.com,smoreland@go per-file build-mainline-modules.sh = ngeoffray@google.com,paulduffin@google.com,mast@google.com per-file build-aml-prebuilts.sh = ngeoffray@google.com,paulduffin@google.com,mast@google.com per-file construct_context.py = ngeoffray@google.com,calin@google.com,mathieuc@google.com,skvadrik@google.com +per-file conv_linker_config.py = kiyoungkim@google.com, jiyong@google.com, jooyung@google.com diff --git a/scripts/conv_linker_config.py b/scripts/conv_linker_config.py new file mode 100644 index 000000000..86f788d81 --- /dev/null +++ b/scripts/conv_linker_config.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python +# +# Copyright (C) 2020 The Android Open Source Project +# +# 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. +""" A tool to convert json file into pb with linker config format.""" + +import argparse +import collections +import json + +import linker_config_pb2 +from google.protobuf.json_format import ParseDict +from google.protobuf.text_format import MessageToString + + +def Proto(args): + with open(args.source) as f: + obj = json.load(f, object_pairs_hook=collections.OrderedDict) + pb = ParseDict(obj, linker_config_pb2.LinkerConfig()) + with open(args.output, 'wb') as f: + f.write(pb.SerializeToString()) + + +def Print(args): + with open(args.source, 'rb') as f: + pb = linker_config_pb2.LinkerConfig() + pb.ParseFromString(f.read()) + print(MessageToString(pb)) + + +def GetArgParser(): + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers() + + parser_proto = subparsers.add_parser( + 'proto', help='Convert the input JSON configuration file into protobuf.') + parser_proto.add_argument( + '-s', + '--source', + required=True, + type=str, + help='Source linker configuration file in JSON.') + parser_proto.add_argument( + '-o', + '--output', + required=True, + type=str, + help='Target path to create protobuf file.') + parser_proto.set_defaults(func=Proto) + + print_proto = subparsers.add_parser( + 'print', help='Print configuration in human-readable text format.') + print_proto.add_argument( + '-s', + '--source', + required=True, + type=str, + help='Source linker configuration file in protobuf.') + print_proto.set_defaults(func=Print) + + return parser + + +def main(): + args = GetArgParser().parse_args() + args.func(args) + + +if __name__ == '__main__': + main() diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go index 480f9b797..edb8b3074 100644 --- a/sysprop/sysprop_library.go +++ b/sysprop/sysprop_library.go @@ -404,13 +404,21 @@ func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) { // ctx's Platform or Specific functions represent where this sysprop_library installed. installedInSystem := ctx.Platform() || ctx.SystemExtSpecific() installedInVendorOrOdm := ctx.SocSpecific() || ctx.DeviceSpecific() + installedInProduct := ctx.ProductSpecific() isOwnerPlatform := false - stub := "sysprop-library-stub-" + var stub string + + if installedInVendorOrOdm { + stub = "sysprop-library-stub-vendor" + } else if installedInProduct { + stub = "sysprop-library-stub-product" + } else { + stub = "sysprop-library-stub-platform" + } switch m.Owner() { case "Platform": // Every partition can access platform-defined properties - stub += "platform" isOwnerPlatform = true case "Vendor": // System can't access vendor's properties @@ -418,14 +426,12 @@ func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) { ctx.ModuleErrorf("None of soc_specific, device_specific, product_specific is true. " + "System can't access sysprop_library owned by Vendor") } - stub += "vendor" case "Odm": // Only vendor can access Odm-defined properties if !installedInVendorOrOdm { ctx.ModuleErrorf("Neither soc_speicifc nor device_specific is true. " + "Odm-defined properties should be accessed only in Vendor or Odm") } - stub += "vendor" default: ctx.PropertyErrorf("property_owner", "Unknown value %s: must be one of Platform, Vendor or Odm", m.Owner()) diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go index 711129c84..3be19459e 100644 --- a/sysprop/sysprop_test.go +++ b/sysprop/sysprop_test.go @@ -103,6 +103,8 @@ func testConfig(env map[string]string, bp string, fs map[string][]byte) android. "api/sysprop-platform-on-product-latest.txt": nil, "api/sysprop-vendor-current.txt": nil, "api/sysprop-vendor-latest.txt": nil, + "api/sysprop-vendor-on-product-current.txt": nil, + "api/sysprop-vendor-on-product-latest.txt": nil, "api/sysprop-odm-current.txt": nil, "api/sysprop-odm-latest.txt": nil, "framework/aidl/a.aidl": nil, @@ -182,8 +184,15 @@ func TestSyspropLibrary(t *testing.T) { srcs: ["com/android/VendorProperties.sysprop"], api_packages: ["com.android"], property_owner: "Vendor", + vendor: true, + } + + sysprop_library { + name: "sysprop-vendor-on-product", + srcs: ["com/android/VendorProperties.sysprop"], + api_packages: ["com.android"], + property_owner: "Vendor", product_specific: true, - vendor_available: true, } sysprop_library { @@ -213,7 +222,7 @@ func TestSyspropLibrary(t *testing.T) { srcs: ["c.java"], sdk_version: "system_current", product_specific: true, - libs: ["sysprop-platform", "sysprop-vendor"], + libs: ["sysprop-platform", "sysprop-vendor-on-product"], } java_library { @@ -240,7 +249,7 @@ func TestSyspropLibrary(t *testing.T) { name: "cc-client-product", srcs: ["d.cpp"], product_specific: true, - static_libs: ["sysprop-platform-on-product", "sysprop-vendor"], + static_libs: ["sysprop-platform-on-product", "sysprop-vendor-on-product"], } cc_library { @@ -290,6 +299,12 @@ func TestSyspropLibrary(t *testing.T) { soc_specific: true, sdk_version: "core_current", } + + java_library { + name: "sysprop-library-stub-product", + product_specific: true, + sdk_version: "core_current", + } `) // Check for generated cc_library @@ -317,13 +332,14 @@ func TestSyspropLibrary(t *testing.T) { expectedApexAvailableOnLibrary, library.ApexProperties.Apex_available) } - // core variant of vendor-owned sysprop_library is for product - ctx.ModuleForTests("libsysprop-vendor", variant) + // product variant of vendor-owned sysprop_library + ctx.ModuleForTests("libsysprop-vendor-on-product", variant) } ctx.ModuleForTests("sysprop-platform", "android_common") ctx.ModuleForTests("sysprop-platform_public", "android_common") ctx.ModuleForTests("sysprop-vendor", "android_common") + ctx.ModuleForTests("sysprop-vendor-on-product", "android_common") // Check for exported includes coreVariant := "android_arm64_armv8-a_static" @@ -336,7 +352,7 @@ func TestSyspropLibrary(t *testing.T) { platformOnProductPath := "libsysprop-platform-on-product/android_arm64_armv8-a_static/gen/sysprop/public/include" vendorInternalPath := "libsysprop-vendor/android_vendor.VER_arm64_armv8-a_static/gen/sysprop/include" - vendorPublicPath := "libsysprop-vendor/android_arm64_armv8-a_static/gen/sysprop/public/include" + vendorPublicPath := "libsysprop-vendor-on-product/android_arm64_armv8-a_static/gen/sysprop/public/include" platformClient := ctx.ModuleForTests("cc-client-platform", coreVariant) platformFlags := platformClient.Rule("cc").Args["cFlags"] diff --git a/tradefed/Android.bp b/tradefed/Android.bp index f4e8334f0..4e4e6a7ee 100644 --- a/tradefed/Android.bp +++ b/tradefed/Android.bp @@ -15,7 +15,7 @@ bootstrap_go_package { bootstrap_go_package { name: "soong-suite-harness", - pkgPath: "android/soong/suite_harness", + pkgPath: "android/soong/tradefed/suite_harness", deps: [ "blueprint", "blueprint-pathtools", @@ -25,7 +25,7 @@ bootstrap_go_package { "soong-java", ], srcs: [ - "tradefed_binary.go", + "suite_harness/tradefed_binary.go", ], pluginFor: ["soong_build"], } diff --git a/tradefed/tradefed_binary.go b/tradefed/suite_harness/tradefed_binary.go index 7960fdc88..a421d8bbb 100644 --- a/tradefed/tradefed_binary.go +++ b/tradefed/suite_harness/tradefed_binary.go @@ -23,7 +23,7 @@ import ( "android/soong/java" ) -var pctx = android.NewPackageContext("android/soong/suite_harness") +var pctx = android.NewPackageContext("android/soong/tradefed/suite_harness") func init() { android.RegisterModuleType("tradefed_binary_host", tradefedBinaryFactory) @@ -80,7 +80,6 @@ func tradefedBinaryLoadHook(tfb *TradefedBinaryProperties) func(ctx android.Load "tradefed", "tradefed-test-framework", "loganalysis", - "hosttestlib", "compatibility-host-util", } diff --git a/ui/build/config.go b/ui/build/config.go index fbe5cd241..82df8a0ba 100644 --- a/ui/build/config.go +++ b/ui/build/config.go @@ -184,15 +184,9 @@ func NewConfig(ctx Context, args ...string) Config { "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") + if ret.UseGoma() || ret.ForceUseGoma() { + ctx.Println("Goma for Android has been deprecated and replaced with RBE. See go/rbe_for_android for instructions on how to use RBE.") + ctx.Fatalln("USE_GOMA / FORCE_USE_GOMA flag is no longer supported.") } // Tell python not to spam the source tree with .pyc files. diff --git a/ui/build/context.go b/ui/build/context.go index 3945ce007..43e1e0faf 100644 --- a/ui/build/context.go +++ b/ui/build/context.go @@ -48,7 +48,7 @@ func (c ContextImpl) BeginTrace(name, desc string) { c.Tracer.Begin(desc, c.Thread) } if c.Metrics != nil { - c.Metrics.TimeTracer.Begin(name, desc, c.Thread) + c.Metrics.EventTracer.Begin(name, desc, c.Thread) } } @@ -58,7 +58,7 @@ func (c ContextImpl) EndTrace() { c.Tracer.End(c.Thread) } if c.Metrics != nil { - c.Metrics.SetTimeMetrics(c.Metrics.TimeTracer.End(c.Thread)) + c.Metrics.SetTimeMetrics(c.Metrics.EventTracer.End(c.Thread)) } } diff --git a/ui/build/kati.go b/ui/build/kati.go index f6d3a5741..f6c0f52a3 100644 --- a/ui/build/kati.go +++ b/ui/build/kati.go @@ -68,6 +68,7 @@ func runKati(ctx Context, config Config, extraSuffix string, args []string, envF "--ninja_suffix=" + config.KatiSuffix() + extraSuffix, "--no_ninja_prelude", "--use_ninja_phony_output", + "--use_ninja_symlink_outputs", "--regen", "--ignore_optional_include=" + filepath.Join(config.OutDir(), "%.P"), "--detect_android_echo", diff --git a/ui/metrics/Android.bp b/ui/metrics/Android.bp index 8188a69e9..95c8f5c24 100644 --- a/ui/metrics/Android.bp +++ b/ui/metrics/Android.bp @@ -23,10 +23,10 @@ bootstrap_go_package { ], srcs: [ "metrics.go", - "time.go", + "event.go", ], testSrcs: [ - "time_test.go", + "event_test.go", ], } diff --git a/ui/metrics/time.go b/ui/metrics/event.go index 401656337..5a62847a5 100644 --- a/ui/metrics/time.go +++ b/ui/metrics/event.go @@ -25,7 +25,7 @@ import ( // for testing purpose only var _now = now -type timeEvent struct { +type event struct { desc string name string @@ -33,26 +33,26 @@ type timeEvent struct { start time.Time } -type TimeTracer interface { +type EventTracer interface { Begin(name, desc string, thread tracer.Thread) End(thread tracer.Thread) soong_metrics_proto.PerfInfo } -type timeTracerImpl struct { - activeEvents []timeEvent +type eventTracerImpl struct { + activeEvents []event } -var _ TimeTracer = &timeTracerImpl{} +var _ EventTracer = &eventTracerImpl{} func now() time.Time { return time.Now() } -func (t *timeTracerImpl) Begin(name, desc string, _ tracer.Thread) { - t.activeEvents = append(t.activeEvents, timeEvent{name: name, desc: desc, start: _now()}) +func (t *eventTracerImpl) Begin(name, desc string, _ tracer.Thread) { + t.activeEvents = append(t.activeEvents, event{name: name, desc: desc, start: _now()}) } -func (t *timeTracerImpl) End(tracer.Thread) soong_metrics_proto.PerfInfo { +func (t *eventTracerImpl) End(tracer.Thread) soong_metrics_proto.PerfInfo { if len(t.activeEvents) < 1 { panic("Internal error: No pending events for endAt to end!") } diff --git a/ui/metrics/time_test.go b/ui/metrics/event_test.go index d73080ab2..6fc0b50d1 100644 --- a/ui/metrics/time_test.go +++ b/ui/metrics/event_test.go @@ -28,14 +28,14 @@ func TestEnd(t *testing.T) { _now = func() time.Time { return startTime.Add(dur) } defer func() { _now = initialNow }() - timeTracer := &timeTracerImpl{} - timeTracer.activeEvents = append(timeTracer.activeEvents, timeEvent{ + eventTracer := &eventTracerImpl{} + eventTracer.activeEvents = append(eventTracer.activeEvents, event{ desc: "test", name: "test", start: startTime, }) - perf := timeTracer.End(tracer.Thread(0)) + perf := eventTracer.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/metrics.go b/ui/metrics/metrics.go index 35d197628..7a3726bc2 100644 --- a/ui/metrics/metrics.go +++ b/ui/metrics/metrics.go @@ -36,14 +36,14 @@ const ( ) type Metrics struct { - metrics soong_metrics_proto.MetricsBase - TimeTracer TimeTracer + metrics soong_metrics_proto.MetricsBase + EventTracer EventTracer } func New() (metrics *Metrics) { m := &Metrics{ - metrics: soong_metrics_proto.MetricsBase{}, - TimeTracer: &timeTracerImpl{}, + metrics: soong_metrics_proto.MetricsBase{}, + EventTracer: &eventTracerImpl{}, } return m } diff --git a/ui/metrics/metrics_proto/metrics.pb.go b/ui/metrics/metrics_proto/metrics.pb.go index e824f6ba2..b8c57750b 100644 --- a/ui/metrics/metrics_proto/metrics.pb.go +++ b/ui/metrics/metrics_proto/metrics.pb.go @@ -152,7 +152,7 @@ func (x *ModuleTypeInfo_BuildSystem) UnmarshalJSON(data []byte) error { } func (ModuleTypeInfo_BuildSystem) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{4, 0} + return fileDescriptor_6039342a2ba47b72, []int{5, 0} } type MetricsBase struct { @@ -529,11 +529,13 @@ type PerfInfo struct { // The real running time. // The number of nanoseconds elapsed since start_time. RealTime *uint64 `protobuf:"varint,4,opt,name=real_time,json=realTime" json:"real_time,omitempty"` - // The number of MB for memory use. - MemoryUse *uint64 `protobuf:"varint,5,opt,name=memory_use,json=memoryUse" json:"memory_use,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + // The number of MB for memory use (deprecated as it is too generic). + MemoryUse *uint64 `protobuf:"varint,5,opt,name=memory_use,json=memoryUse" json:"memory_use,omitempty"` // Deprecated: Do not use. + // The resource information of each executed process. + ProcessesResourceInfo []*ProcessResourceInfo `protobuf:"bytes,6,rep,name=processes_resource_info,json=processesResourceInfo" json:"processes_resource_info,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *PerfInfo) Reset() { *m = PerfInfo{} } @@ -589,6 +591,7 @@ func (m *PerfInfo) GetRealTime() uint64 { return 0 } +// Deprecated: Do not use. func (m *PerfInfo) GetMemoryUse() uint64 { if m != nil && m.MemoryUse != nil { return *m.MemoryUse @@ -596,6 +599,134 @@ func (m *PerfInfo) GetMemoryUse() uint64 { return 0 } +func (m *PerfInfo) GetProcessesResourceInfo() []*ProcessResourceInfo { + if m != nil { + return m.ProcessesResourceInfo + } + return nil +} + +type ProcessResourceInfo struct { + // The name of the process for identification. + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // The amount of time spent executing in user space in microseconds. + UserTimeMicros *uint64 `protobuf:"varint,2,opt,name=user_time_micros,json=userTimeMicros" json:"user_time_micros,omitempty"` + // The amount of time spent executing in kernel mode in microseconds. + SystemTimeMicros *uint64 `protobuf:"varint,3,opt,name=system_time_micros,json=systemTimeMicros" json:"system_time_micros,omitempty"` + // The maximum resident set size memory used in kilobytes. + MaxRssKb *uint64 `protobuf:"varint,4,opt,name=max_rss_kb,json=maxRssKb" json:"max_rss_kb,omitempty"` + // The number of minor page faults serviced without any I/O activity. + MinorPageFaults *uint64 `protobuf:"varint,5,opt,name=minor_page_faults,json=minorPageFaults" json:"minor_page_faults,omitempty"` + // The number of major page faults serviced that required I/O activity. + MajorPageFaults *uint64 `protobuf:"varint,6,opt,name=major_page_faults,json=majorPageFaults" json:"major_page_faults,omitempty"` + // Total IO input in kilobytes. + IoInputKb *uint64 `protobuf:"varint,7,opt,name=io_input_kb,json=ioInputKb" json:"io_input_kb,omitempty"` + // Total IO output in kilobytes. + IoOutputKb *uint64 `protobuf:"varint,8,opt,name=io_output_kb,json=ioOutputKb" json:"io_output_kb,omitempty"` + // The number of voluntary context switches + VoluntaryContextSwitches *uint64 `protobuf:"varint,9,opt,name=voluntary_context_switches,json=voluntaryContextSwitches" json:"voluntary_context_switches,omitempty"` + // The number of involuntary context switches + InvoluntaryContextSwitches *uint64 `protobuf:"varint,10,opt,name=involuntary_context_switches,json=involuntaryContextSwitches" json:"involuntary_context_switches,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ProcessResourceInfo) Reset() { *m = ProcessResourceInfo{} } +func (m *ProcessResourceInfo) String() string { return proto.CompactTextString(m) } +func (*ProcessResourceInfo) ProtoMessage() {} +func (*ProcessResourceInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_6039342a2ba47b72, []int{4} +} + +func (m *ProcessResourceInfo) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ProcessResourceInfo.Unmarshal(m, b) +} +func (m *ProcessResourceInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ProcessResourceInfo.Marshal(b, m, deterministic) +} +func (m *ProcessResourceInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_ProcessResourceInfo.Merge(m, src) +} +func (m *ProcessResourceInfo) XXX_Size() int { + return xxx_messageInfo_ProcessResourceInfo.Size(m) +} +func (m *ProcessResourceInfo) XXX_DiscardUnknown() { + xxx_messageInfo_ProcessResourceInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_ProcessResourceInfo proto.InternalMessageInfo + +func (m *ProcessResourceInfo) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *ProcessResourceInfo) GetUserTimeMicros() uint64 { + if m != nil && m.UserTimeMicros != nil { + return *m.UserTimeMicros + } + return 0 +} + +func (m *ProcessResourceInfo) GetSystemTimeMicros() uint64 { + if m != nil && m.SystemTimeMicros != nil { + return *m.SystemTimeMicros + } + return 0 +} + +func (m *ProcessResourceInfo) GetMaxRssKb() uint64 { + if m != nil && m.MaxRssKb != nil { + return *m.MaxRssKb + } + return 0 +} + +func (m *ProcessResourceInfo) GetMinorPageFaults() uint64 { + if m != nil && m.MinorPageFaults != nil { + return *m.MinorPageFaults + } + return 0 +} + +func (m *ProcessResourceInfo) GetMajorPageFaults() uint64 { + if m != nil && m.MajorPageFaults != nil { + return *m.MajorPageFaults + } + return 0 +} + +func (m *ProcessResourceInfo) GetIoInputKb() uint64 { + if m != nil && m.IoInputKb != nil { + return *m.IoInputKb + } + return 0 +} + +func (m *ProcessResourceInfo) GetIoOutputKb() uint64 { + if m != nil && m.IoOutputKb != nil { + return *m.IoOutputKb + } + return 0 +} + +func (m *ProcessResourceInfo) GetVoluntaryContextSwitches() uint64 { + if m != nil && m.VoluntaryContextSwitches != nil { + return *m.VoluntaryContextSwitches + } + return 0 +} + +func (m *ProcessResourceInfo) GetInvoluntaryContextSwitches() uint64 { + if m != nil && m.InvoluntaryContextSwitches != nil { + return *m.InvoluntaryContextSwitches + } + return 0 +} + type ModuleTypeInfo struct { // The build system, eg. Soong or Make. BuildSystem *ModuleTypeInfo_BuildSystem `protobuf:"varint,1,opt,name=build_system,json=buildSystem,enum=soong_build_metrics.ModuleTypeInfo_BuildSystem,def=0" json:"build_system,omitempty"` @@ -612,7 +743,7 @@ func (m *ModuleTypeInfo) Reset() { *m = ModuleTypeInfo{} } func (m *ModuleTypeInfo) String() string { return proto.CompactTextString(m) } func (*ModuleTypeInfo) ProtoMessage() {} func (*ModuleTypeInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{4} + return fileDescriptor_6039342a2ba47b72, []int{5} } func (m *ModuleTypeInfo) XXX_Unmarshal(b []byte) error { @@ -670,7 +801,7 @@ func (m *CriticalUserJourneyMetrics) Reset() { *m = CriticalUserJourneyM func (m *CriticalUserJourneyMetrics) String() string { return proto.CompactTextString(m) } func (*CriticalUserJourneyMetrics) ProtoMessage() {} func (*CriticalUserJourneyMetrics) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{5} + return fileDescriptor_6039342a2ba47b72, []int{6} } func (m *CriticalUserJourneyMetrics) XXX_Unmarshal(b []byte) error { @@ -717,7 +848,7 @@ func (m *CriticalUserJourneysMetrics) Reset() { *m = CriticalUserJourney func (m *CriticalUserJourneysMetrics) String() string { return proto.CompactTextString(m) } func (*CriticalUserJourneysMetrics) ProtoMessage() {} func (*CriticalUserJourneysMetrics) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{6} + return fileDescriptor_6039342a2ba47b72, []int{7} } func (m *CriticalUserJourneysMetrics) XXX_Unmarshal(b []byte) error { @@ -765,7 +896,7 @@ func (m *SoongBuildMetrics) Reset() { *m = SoongBuildMetrics{} } func (m *SoongBuildMetrics) String() string { return proto.CompactTextString(m) } func (*SoongBuildMetrics) ProtoMessage() {} func (*SoongBuildMetrics) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{7} + return fileDescriptor_6039342a2ba47b72, []int{8} } func (m *SoongBuildMetrics) XXX_Unmarshal(b []byte) error { @@ -829,6 +960,7 @@ func init() { proto.RegisterType((*BuildConfig)(nil), "soong_build_metrics.BuildConfig") proto.RegisterType((*SystemResourceInfo)(nil), "soong_build_metrics.SystemResourceInfo") proto.RegisterType((*PerfInfo)(nil), "soong_build_metrics.PerfInfo") + proto.RegisterType((*ProcessResourceInfo)(nil), "soong_build_metrics.ProcessResourceInfo") proto.RegisterType((*ModuleTypeInfo)(nil), "soong_build_metrics.ModuleTypeInfo") proto.RegisterType((*CriticalUserJourneyMetrics)(nil), "soong_build_metrics.CriticalUserJourneyMetrics") proto.RegisterType((*CriticalUserJourneysMetrics)(nil), "soong_build_metrics.CriticalUserJourneysMetrics") @@ -840,76 +972,90 @@ func init() { } var fileDescriptor_6039342a2ba47b72 = []byte{ - // 1130 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0x6f, 0x6f, 0xd4, 0x46, - 0x13, 0xc7, 0xc9, 0x25, 0x77, 0x1e, 0xe7, 0x0e, 0x67, 0x13, 0x1e, 0x0c, 0x08, 0x3d, 0x91, 0x55, - 0x68, 0x54, 0x95, 0x80, 0xae, 0x28, 0x42, 0x11, 0xaa, 0x94, 0x1c, 0x11, 0xa5, 0xe8, 0x72, 0x68, - 0xc3, 0x51, 0xda, 0xbe, 0xb0, 0xf6, 0xec, 0xbd, 0xc4, 0xd4, 0xf6, 0x5a, 0xbb, 0x6b, 0xc4, 0xf1, - 0x1d, 0xfa, 0xa9, 0xfa, 0x59, 0xfa, 0x11, 0xfa, 0xbe, 0xda, 0x59, 0xfb, 0xee, 0x28, 0xd7, 0x82, - 0x78, 0x77, 0x9e, 0xdf, 0x9f, 0x9d, 0x19, 0x8f, 0x67, 0x0f, 0xba, 0x39, 0xd7, 0x32, 0x8d, 0xd5, - 0x41, 0x29, 0x85, 0x16, 0x64, 0x47, 0x09, 0x51, 0x5c, 0x44, 0x93, 0x2a, 0xcd, 0x92, 0xa8, 0x86, - 0xc2, 0xbf, 0x3c, 0xf0, 0x86, 0xf6, 0xf7, 0x09, 0x53, 0x9c, 0x3c, 0x80, 0x5d, 0x4b, 0x48, 0x98, - 0xe6, 0x91, 0x4e, 0x73, 0xae, 0x34, 0xcb, 0xcb, 0xc0, 0xd9, 0x73, 0xf6, 0xd7, 0x29, 0x41, 0xec, - 0x09, 0xd3, 0xfc, 0x65, 0x83, 0x90, 0x1b, 0xd0, 0xb1, 0x8a, 0x34, 0x09, 0xd6, 0xf6, 0x9c, 0x7d, - 0x97, 0xb6, 0xf1, 0xf9, 0x59, 0x42, 0x8e, 0xe0, 0x46, 0x99, 0x31, 0x3d, 0x15, 0x32, 0x8f, 0xde, - 0x72, 0xa9, 0x52, 0x51, 0x44, 0xb1, 0x48, 0x78, 0xc1, 0x72, 0x1e, 0xac, 0x23, 0xf7, 0x7a, 0x43, - 0x78, 0x65, 0xf1, 0x41, 0x0d, 0x93, 0x3b, 0xd0, 0xd3, 0x4c, 0x5e, 0x70, 0x1d, 0x95, 0x52, 0x24, - 0x55, 0xac, 0x83, 0x16, 0x0a, 0xba, 0x36, 0xfa, 0xc2, 0x06, 0x49, 0x02, 0xbb, 0x35, 0xcd, 0x26, - 0xf1, 0x96, 0xc9, 0x94, 0x15, 0x3a, 0xd8, 0xd8, 0x73, 0xf6, 0x7b, 0xfd, 0x7b, 0x07, 0x2b, 0x6a, - 0x3e, 0x58, 0xaa, 0xf7, 0xe0, 0xc4, 0x20, 0xaf, 0xac, 0xe8, 0x68, 0xfd, 0xf4, 0xec, 0x29, 0x25, - 0xd6, 0x6f, 0x19, 0x20, 0x23, 0xf0, 0xea, 0x53, 0x98, 0x8c, 0x2f, 0x83, 0x4d, 0x34, 0xbf, 0xf3, - 0x49, 0xf3, 0x63, 0x19, 0x5f, 0x1e, 0xb5, 0xc7, 0x67, 0xcf, 0xcf, 0x46, 0x3f, 0x9d, 0x51, 0xb0, - 0x16, 0x26, 0x48, 0x0e, 0x60, 0x67, 0xc9, 0x70, 0x9e, 0x75, 0x1b, 0x4b, 0xdc, 0x5e, 0x10, 0x9b, - 0x04, 0xbe, 0x85, 0x3a, 0xad, 0x28, 0x2e, 0xab, 0x39, 0xbd, 0x83, 0x74, 0xdf, 0x22, 0x83, 0xb2, - 0x6a, 0xd8, 0xcf, 0xc1, 0xbd, 0x14, 0xaa, 0x4e, 0xd6, 0xfd, 0xa2, 0x64, 0x3b, 0xc6, 0x00, 0x53, - 0xa5, 0xd0, 0x45, 0xb3, 0x7e, 0x91, 0x58, 0x43, 0xf8, 0x22, 0x43, 0xcf, 0x98, 0xf4, 0x8b, 0x04, - 0x3d, 0xaf, 0x43, 0x1b, 0x3d, 0x85, 0x0a, 0x3c, 0xac, 0x61, 0xd3, 0x3c, 0x8e, 0x14, 0x09, 0xeb, - 0xc3, 0x84, 0x8a, 0xf8, 0x3b, 0x2d, 0x59, 0xb0, 0x85, 0xb0, 0x67, 0xe1, 0x53, 0x13, 0x9a, 0x73, - 0x62, 0x29, 0x94, 0x32, 0x16, 0xdd, 0x05, 0x67, 0x60, 0x62, 0x23, 0x45, 0xee, 0xc2, 0xd5, 0x25, - 0x0e, 0xa6, 0xdd, 0xb3, 0xe3, 0x33, 0x67, 0x61, 0x22, 0xf7, 0x60, 0x67, 0x89, 0x37, 0x2f, 0xf1, - 0xaa, 0x6d, 0xec, 0x9c, 0xbb, 0x94, 0xb7, 0xa8, 0x74, 0x94, 0xa4, 0x32, 0xf0, 0x6d, 0xde, 0xa2, - 0xd2, 0x4f, 0x52, 0x49, 0xbe, 0x07, 0x4f, 0x71, 0x5d, 0x95, 0x91, 0x16, 0x22, 0x53, 0xc1, 0xf6, - 0xde, 0xfa, 0xbe, 0xd7, 0xbf, 0xbd, 0xb2, 0x45, 0x2f, 0xb8, 0x9c, 0x3e, 0x2b, 0xa6, 0x82, 0x02, - 0x2a, 0x5e, 0x1a, 0x01, 0x39, 0x02, 0xf7, 0x37, 0xa6, 0xd3, 0x48, 0x56, 0x85, 0x0a, 0xc8, 0xe7, - 0xa8, 0x3b, 0x86, 0x4f, 0xab, 0x42, 0x91, 0xc7, 0x00, 0x96, 0x89, 0xe2, 0x9d, 0xcf, 0x11, 0xbb, - 0x88, 0x36, 0xea, 0x22, 0x2d, 0xde, 0x30, 0xab, 0xde, 0xfd, 0x2c, 0x35, 0x0a, 0x50, 0xfd, 0x1d, - 0x6c, 0x68, 0xa1, 0x59, 0x16, 0x5c, 0xdb, 0x73, 0x3e, 0x2d, 0xb4, 0x5c, 0xf2, 0x0a, 0x56, 0xad, - 0xa2, 0xe0, 0x7f, 0x68, 0x71, 0x77, 0xa5, 0xc5, 0xb9, 0x89, 0xe1, 0x27, 0x59, 0x4f, 0x18, 0xdd, - 0x56, 0xff, 0x0c, 0x91, 0x01, 0x6c, 0x59, 0x55, 0x2c, 0x8a, 0x69, 0x7a, 0x11, 0x5c, 0x47, 0xc3, - 0xbd, 0x95, 0x86, 0x28, 0x1c, 0x20, 0x8f, 0x7a, 0x93, 0xc5, 0x03, 0xb9, 0x09, 0x38, 0xfa, 0xb8, - 0xa2, 0x02, 0x7c, 0xc7, 0xf3, 0x67, 0xf2, 0x33, 0xec, 0xaa, 0x99, 0xd2, 0x3c, 0x8f, 0x24, 0x57, - 0xa2, 0x92, 0x31, 0x8f, 0xd2, 0x62, 0x2a, 0x82, 0x1b, 0x78, 0xd0, 0xd7, 0xab, 0x33, 0x47, 0x01, - 0xad, 0xf9, 0xd8, 0x06, 0xa2, 0x3e, 0x8a, 0x85, 0x0f, 0x60, 0xeb, 0x83, 0x8d, 0xd3, 0x81, 0xd6, - 0xf8, 0xfc, 0x94, 0xfa, 0x57, 0x48, 0x17, 0x5c, 0xf3, 0xeb, 0xc9, 0xe9, 0xc9, 0xf8, 0xa9, 0xef, - 0x90, 0x36, 0x98, 0x2d, 0xe5, 0xaf, 0x85, 0x8f, 0xa1, 0x85, 0x33, 0xe9, 0x41, 0xf3, 0x8d, 0xf9, - 0x57, 0x0c, 0x7a, 0x4c, 0x87, 0xbe, 0x43, 0x5c, 0xd8, 0x38, 0xa6, 0xc3, 0xc3, 0x87, 0xfe, 0x9a, - 0x89, 0xbd, 0x7e, 0x74, 0xe8, 0xaf, 0x13, 0x80, 0xcd, 0xd7, 0x8f, 0x0e, 0xa3, 0xc3, 0x87, 0x7e, - 0x2b, 0xbc, 0x00, 0x6f, 0xa9, 0x05, 0x66, 0x89, 0x57, 0x8a, 0x47, 0x17, 0x22, 0x67, 0xb8, 0xea, - 0x3b, 0xb4, 0x5d, 0x29, 0xfe, 0x54, 0xe4, 0xcc, 0xcc, 0xbc, 0x81, 0xe4, 0x84, 0xe3, 0x7a, 0xef, - 0xd0, 0xcd, 0x4a, 0x71, 0x3a, 0xe1, 0xe4, 0x2b, 0xe8, 0x4d, 0x85, 0xe9, 0xc1, 0x5c, 0xb9, 0x8e, - 0xf8, 0x16, 0x46, 0xc7, 0x56, 0x1e, 0x0a, 0x20, 0x1f, 0xb7, 0x80, 0xf4, 0xe1, 0x1a, 0xce, 0x42, - 0x54, 0x5e, 0xce, 0x54, 0x1a, 0xb3, 0x2c, 0xca, 0x79, 0x2e, 0xe4, 0x0c, 0x0f, 0x6f, 0xd1, 0x1d, - 0x04, 0x5f, 0xd4, 0xd8, 0x10, 0x21, 0x73, 0x23, 0xb0, 0xb7, 0x2c, 0xcd, 0xd8, 0x24, 0xe3, 0x66, - 0x0d, 0x2a, 0xcc, 0x67, 0x83, 0x76, 0xe7, 0xd1, 0x41, 0x59, 0xa9, 0xf0, 0x77, 0x07, 0x3a, 0xcd, - 0xc4, 0x11, 0x02, 0xad, 0x84, 0xab, 0x18, 0x6d, 0x5d, 0x8a, 0xbf, 0x4d, 0x0c, 0xdf, 0xae, 0xbd, - 0xac, 0xf0, 0x37, 0xb9, 0x0d, 0xa0, 0x34, 0x93, 0x1a, 0x6f, 0x3c, 0xac, 0xa3, 0x45, 0x5d, 0x8c, - 0x98, 0x8b, 0x8e, 0xdc, 0x02, 0x57, 0x72, 0x96, 0x59, 0xb4, 0x85, 0x68, 0xc7, 0x04, 0x10, 0xbc, - 0x0d, 0x60, 0x93, 0x37, 0x8d, 0xc0, 0x8b, 0xa7, 0x45, 0x5d, 0x1b, 0x19, 0x2b, 0x1e, 0xfe, 0xe9, - 0x40, 0x6f, 0x28, 0x92, 0x2a, 0xe3, 0x2f, 0x67, 0xa5, 0xad, 0xfe, 0xd7, 0x66, 0x50, 0xed, 0x20, - 0x60, 0x76, 0xbd, 0xfe, 0xfd, 0xd5, 0x1b, 0xf5, 0x03, 0xa9, 0x9d, 0x5b, 0xdb, 0xd0, 0xa5, 0xdd, - 0x3a, 0x59, 0x44, 0xc9, 0xff, 0xc1, 0xcb, 0x51, 0x13, 0xe9, 0x59, 0xd9, 0x54, 0x09, 0xf9, 0xdc, - 0xc6, 0xbc, 0xb7, 0xa2, 0xca, 0x23, 0x31, 0x8d, 0x6c, 0x50, 0x61, 0xbd, 0x5d, 0xba, 0x55, 0x54, - 0xf9, 0x68, 0x6a, 0xcf, 0x53, 0xe1, 0xfd, 0x7a, 0x40, 0x6a, 0xd7, 0x0f, 0xa6, 0xcc, 0x85, 0x8d, - 0xf3, 0xd1, 0xe8, 0xcc, 0x8c, 0x63, 0x07, 0x5a, 0xc3, 0xe3, 0xe7, 0xa7, 0xfe, 0x5a, 0x98, 0xc1, - 0xcd, 0x81, 0x4c, 0xb5, 0x79, 0x61, 0x63, 0xc5, 0xe5, 0x8f, 0xa2, 0x92, 0x05, 0x9f, 0x35, 0xdf, - 0x66, 0xd3, 0x74, 0x67, 0xa9, 0xe9, 0x47, 0xd0, 0x6e, 0xbe, 0xfd, 0xb5, 0xff, 0xf8, 0x54, 0x97, - 0xee, 0x14, 0xda, 0x08, 0xc2, 0x09, 0xdc, 0x5a, 0x71, 0x9a, 0x5a, 0xac, 0x82, 0x56, 0x5c, 0xbd, - 0x51, 0x81, 0x83, 0xfb, 0x6c, 0x75, 0x67, 0xff, 0x3d, 0x5b, 0x8a, 0xe2, 0xf0, 0x0f, 0x07, 0xb6, - 0x3f, 0x5a, 0x3c, 0x24, 0x80, 0x76, 0xd3, 0x37, 0x07, 0xfb, 0xd6, 0x3c, 0x9a, 0xd5, 0x51, 0xdf, - 0xcc, 0xb6, 0xa0, 0x2e, 0x9d, 0x3f, 0x93, 0x6f, 0x60, 0xdb, 0x0e, 0x3c, 0xcb, 0x32, 0x11, 0x47, - 0xb1, 0xa8, 0x0a, 0x5d, 0xcf, 0xd9, 0x55, 0x04, 0x8e, 0x4d, 0x7c, 0x60, 0xc2, 0x64, 0x1f, 0xfc, - 0x65, 0xae, 0x4a, 0xdf, 0x37, 0x43, 0xd7, 0x5b, 0x50, 0xcf, 0xd3, 0xf7, 0xdc, 0x5c, 0x85, 0x39, - 0x7b, 0x17, 0x5d, 0x72, 0x56, 0x5a, 0x9a, 0x9d, 0x3e, 0x2f, 0x67, 0xef, 0x7e, 0xe0, 0xac, 0x34, - 0x9c, 0x93, 0x6b, 0xbf, 0xd4, 0xdb, 0xb6, 0xae, 0x3b, 0xc2, 0x7f, 0x83, 0x7f, 0x07, 0x00, 0x00, - 0xff, 0xff, 0xa3, 0xdd, 0xbb, 0xb3, 0x1d, 0x0a, 0x00, 0x00, + // 1347 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x57, 0x6f, 0x4f, 0x1b, 0xc7, + 0x13, 0x8e, 0xc1, 0x60, 0x7b, 0x8c, 0x8d, 0x59, 0xe0, 0xc7, 0x85, 0x24, 0xbf, 0x52, 0xab, 0x49, + 0x51, 0xd5, 0x90, 0x88, 0x46, 0x28, 0x42, 0x51, 0x55, 0x70, 0x68, 0x9a, 0x22, 0x30, 0x5a, 0x42, + 0x9a, 0xb6, 0x2f, 0xb6, 0xeb, 0xf3, 0x1a, 0x2e, 0xb9, 0xbb, 0x3d, 0xed, 0xee, 0x51, 0x9c, 0x6f, + 0xd6, 0xd7, 0xfd, 0x2c, 0xfd, 0x04, 0x55, 0xdf, 0x57, 0x3b, 0x7b, 0x77, 0x1c, 0xc4, 0x4d, 0xa2, + 0xbc, 0xbb, 0x9b, 0xe7, 0x79, 0x66, 0x67, 0xe7, 0xe6, 0x8f, 0x0d, 0xad, 0x48, 0x18, 0x15, 0xf8, + 0x7a, 0x23, 0x51, 0xd2, 0x48, 0xb2, 0xa8, 0xa5, 0x8c, 0x4f, 0xd9, 0x20, 0x0d, 0xc2, 0x21, 0xcb, + 0xa0, 0xee, 0x3f, 0x4d, 0x68, 0x1e, 0xb8, 0xe7, 0x5d, 0xae, 0x05, 0x79, 0x08, 0x4b, 0x8e, 0x30, + 0xe4, 0x46, 0x30, 0x13, 0x44, 0x42, 0x1b, 0x1e, 0x25, 0x5e, 0x65, 0xad, 0xb2, 0x3e, 0x4d, 0x09, + 0x62, 0x4f, 0xb9, 0x11, 0x2f, 0x72, 0x84, 0xdc, 0x84, 0xba, 0x53, 0x04, 0x43, 0x6f, 0x6a, 0xad, + 0xb2, 0xde, 0xa0, 0x35, 0x7c, 0x7f, 0x3e, 0x24, 0xdb, 0x70, 0x33, 0x09, 0xb9, 0x19, 0x49, 0x15, + 0xb1, 0x73, 0xa1, 0x74, 0x20, 0x63, 0xe6, 0xcb, 0xa1, 0x88, 0x79, 0x24, 0xbc, 0x69, 0xe4, 0xae, + 0xe4, 0x84, 0x97, 0x0e, 0xef, 0x65, 0x30, 0xb9, 0x0b, 0x6d, 0xc3, 0xd5, 0xa9, 0x30, 0x2c, 0x51, + 0x72, 0x98, 0xfa, 0xc6, 0xab, 0xa2, 0xa0, 0xe5, 0xac, 0x47, 0xce, 0x48, 0x86, 0xb0, 0x94, 0xd1, + 0x5c, 0x10, 0xe7, 0x5c, 0x05, 0x3c, 0x36, 0xde, 0xcc, 0x5a, 0x65, 0xbd, 0xbd, 0x79, 0x7f, 0x63, + 0xc2, 0x9d, 0x37, 0x4a, 0xf7, 0xdd, 0xd8, 0xb5, 0xc8, 0x4b, 0x27, 0xda, 0x9e, 0xde, 0x3b, 0x7c, + 0x46, 0x89, 0xf3, 0x57, 0x06, 0x48, 0x1f, 0x9a, 0xd9, 0x29, 0x5c, 0xf9, 0x67, 0xde, 0x2c, 0x3a, + 0xbf, 0xfb, 0x41, 0xe7, 0x3b, 0xca, 0x3f, 0xdb, 0xae, 0x9d, 0x1c, 0xee, 0x1f, 0xf6, 0x7f, 0x3a, + 0xa4, 0xe0, 0x5c, 0x58, 0x23, 0xd9, 0x80, 0xc5, 0x92, 0xc3, 0x22, 0xea, 0x1a, 0x5e, 0x71, 0xe1, + 0x92, 0x98, 0x07, 0xf0, 0x35, 0x64, 0x61, 0x31, 0x3f, 0x49, 0x0b, 0x7a, 0x1d, 0xe9, 0x1d, 0x87, + 0xf4, 0x92, 0x34, 0x67, 0xef, 0x43, 0xe3, 0x4c, 0xea, 0x2c, 0xd8, 0xc6, 0x27, 0x05, 0x5b, 0xb7, + 0x0e, 0x30, 0x54, 0x0a, 0x2d, 0x74, 0xb6, 0x19, 0x0f, 0x9d, 0x43, 0xf8, 0x24, 0x87, 0x4d, 0xeb, + 0x64, 0x33, 0x1e, 0xa2, 0xcf, 0x15, 0xa8, 0xa1, 0x4f, 0xa9, 0xbd, 0x26, 0xde, 0x61, 0xd6, 0xbe, + 0xf6, 0x35, 0xe9, 0x66, 0x87, 0x49, 0xcd, 0xc4, 0x85, 0x51, 0xdc, 0x9b, 0x43, 0xb8, 0xe9, 0xe0, + 0x3d, 0x6b, 0x2a, 0x38, 0xbe, 0x92, 0x5a, 0x5b, 0x17, 0xad, 0x4b, 0x4e, 0xcf, 0xda, 0xfa, 0x9a, + 0xdc, 0x83, 0xf9, 0x12, 0x07, 0xc3, 0x6e, 0xbb, 0xf2, 0x29, 0x58, 0x18, 0xc8, 0x7d, 0x58, 0x2c, + 0xf1, 0x8a, 0x2b, 0xce, 0xbb, 0xc4, 0x16, 0xdc, 0x52, 0xdc, 0x32, 0x35, 0x6c, 0x18, 0x28, 0xaf, + 0xe3, 0xe2, 0x96, 0xa9, 0x79, 0x1a, 0x28, 0xf2, 0x2d, 0x34, 0xb5, 0x30, 0x69, 0xc2, 0x8c, 0x94, + 0xa1, 0xf6, 0x16, 0xd6, 0xa6, 0xd7, 0x9b, 0x9b, 0x77, 0x26, 0xa6, 0xe8, 0x48, 0xa8, 0xd1, 0xf3, + 0x78, 0x24, 0x29, 0xa0, 0xe2, 0x85, 0x15, 0x90, 0x6d, 0x68, 0xbc, 0xe1, 0x26, 0x60, 0x2a, 0x8d, + 0xb5, 0x47, 0x3e, 0x46, 0x5d, 0xb7, 0x7c, 0x9a, 0xc6, 0x9a, 0x3c, 0x01, 0x70, 0x4c, 0x14, 0x2f, + 0x7e, 0x8c, 0xb8, 0x81, 0x68, 0xae, 0x8e, 0x83, 0xf8, 0x35, 0x77, 0xea, 0xa5, 0x8f, 0x52, 0xa3, + 0x00, 0xd5, 0xdf, 0xc0, 0x8c, 0x91, 0x86, 0x87, 0xde, 0xf2, 0x5a, 0xe5, 0xc3, 0x42, 0xc7, 0x25, + 0x2f, 0x61, 0xd2, 0x28, 0xf2, 0xfe, 0x87, 0x2e, 0xee, 0x4d, 0x74, 0x71, 0x6c, 0x6d, 0xd8, 0x92, + 0x59, 0x85, 0xd1, 0x05, 0x7d, 0xdd, 0x44, 0x7a, 0x30, 0xe7, 0x54, 0xbe, 0x8c, 0x47, 0xc1, 0xa9, + 0xb7, 0x82, 0x0e, 0xd7, 0x26, 0x3a, 0x44, 0x61, 0x0f, 0x79, 0xb4, 0x39, 0xb8, 0x7c, 0x21, 0xab, + 0x80, 0xa5, 0x8f, 0x23, 0xca, 0xc3, 0x6f, 0x5c, 0xbc, 0x93, 0x9f, 0x61, 0x49, 0x8f, 0xb5, 0x11, + 0x11, 0x53, 0x42, 0xcb, 0x54, 0xf9, 0x82, 0x05, 0xf1, 0x48, 0x7a, 0x37, 0xf1, 0xa0, 0x2f, 0x27, + 0x47, 0x8e, 0x02, 0x9a, 0xf1, 0x31, 0x0d, 0x44, 0xbf, 0x63, 0xeb, 0x3e, 0x84, 0xb9, 0x2b, 0x13, + 0xa7, 0x0e, 0xd5, 0x93, 0xe3, 0x3d, 0xda, 0xb9, 0x41, 0x5a, 0xd0, 0xb0, 0x4f, 0x4f, 0xf7, 0x76, + 0x4f, 0x9e, 0x75, 0x2a, 0xa4, 0x06, 0x76, 0x4a, 0x75, 0xa6, 0xba, 0x4f, 0xa0, 0x8a, 0x35, 0xd9, + 0x84, 0xbc, 0xc7, 0x3a, 0x37, 0x2c, 0xba, 0x43, 0x0f, 0x3a, 0x15, 0xd2, 0x80, 0x99, 0x1d, 0x7a, + 0xb0, 0xf5, 0xa8, 0x33, 0x65, 0x6d, 0xaf, 0x1e, 0x6f, 0x75, 0xa6, 0x09, 0xc0, 0xec, 0xab, 0xc7, + 0x5b, 0x6c, 0xeb, 0x51, 0xa7, 0xda, 0x3d, 0x85, 0x66, 0x29, 0x05, 0x76, 0x88, 0xa7, 0x5a, 0xb0, + 0x53, 0x19, 0x71, 0x1c, 0xf5, 0x75, 0x5a, 0x4b, 0xb5, 0x78, 0x26, 0x23, 0x6e, 0x6b, 0xde, 0x42, + 0x6a, 0x20, 0x70, 0xbc, 0xd7, 0xe9, 0x6c, 0xaa, 0x05, 0x1d, 0x08, 0xf2, 0x05, 0xb4, 0x47, 0xd2, + 0xe6, 0xa0, 0x50, 0x4e, 0x23, 0x3e, 0x87, 0xd6, 0x13, 0x27, 0xef, 0x4a, 0x20, 0xef, 0xa6, 0x80, + 0x6c, 0xc2, 0x32, 0xd6, 0x02, 0x4b, 0xce, 0xc6, 0x3a, 0xf0, 0x79, 0xc8, 0x22, 0x11, 0x49, 0x35, + 0xc6, 0xc3, 0xab, 0x74, 0x11, 0xc1, 0xa3, 0x0c, 0x3b, 0x40, 0xc8, 0x6e, 0x04, 0x7e, 0xce, 0x83, + 0x90, 0x0f, 0x42, 0x61, 0xc7, 0xa0, 0xc6, 0x78, 0x66, 0x68, 0xab, 0xb0, 0xf6, 0x92, 0x54, 0x77, + 0xff, 0xae, 0x40, 0x3d, 0xaf, 0x38, 0x42, 0xa0, 0x3a, 0x14, 0xda, 0x47, 0xb7, 0x0d, 0x8a, 0xcf, + 0xd6, 0x86, 0x5f, 0xd7, 0x2d, 0x2b, 0x7c, 0x26, 0x77, 0x00, 0xb4, 0xe1, 0xca, 0xe0, 0xc6, 0xc3, + 0x7b, 0x54, 0x69, 0x03, 0x2d, 0x76, 0xd1, 0x91, 0x5b, 0xd0, 0x50, 0x82, 0x87, 0x0e, 0xad, 0x22, + 0x5a, 0xb7, 0x06, 0x04, 0x3f, 0x07, 0x70, 0xc1, 0xdb, 0x44, 0xe0, 0xe2, 0xa9, 0xee, 0x4e, 0x79, + 0x15, 0xda, 0x70, 0xd6, 0x13, 0x2d, 0xc8, 0x6f, 0xb0, 0x92, 0x28, 0xe9, 0x0b, 0xad, 0x85, 0xbe, + 0x56, 0x3b, 0xb3, 0xd8, 0x71, 0xeb, 0x93, 0x1b, 0xc7, 0x69, 0xae, 0x14, 0xcf, 0x72, 0xe1, 0xe8, + 0x4a, 0xfd, 0xfc, 0x31, 0x0d, 0x8b, 0x13, 0xe8, 0xc5, 0x65, 0x2b, 0xa5, 0xcb, 0xae, 0x43, 0x27, + 0xd5, 0x42, 0xe1, 0x6d, 0x58, 0x14, 0xd8, 0xd9, 0x87, 0xc9, 0xa8, 0xd2, 0xb6, 0xb5, 0xdb, 0x4b, + 0x1d, 0xa0, 0xd5, 0xae, 0x9d, 0xac, 0xe0, 0xcb, 0x5c, 0x97, 0x9e, 0x8e, 0x43, 0x4a, 0xec, 0xdb, + 0x00, 0x11, 0xbf, 0x60, 0x4a, 0x6b, 0xf6, 0x66, 0x90, 0xa7, 0x29, 0xe2, 0x17, 0x54, 0xeb, 0xfd, + 0x01, 0xf9, 0x0a, 0x16, 0xa2, 0x20, 0x96, 0x8a, 0x25, 0xfc, 0x54, 0xb0, 0x11, 0x4f, 0x43, 0xa3, + 0x5d, 0xb6, 0xe8, 0x3c, 0x02, 0x47, 0xfc, 0x54, 0x7c, 0x8f, 0x66, 0xe4, 0xf2, 0xd7, 0xd7, 0xb8, + 0xb3, 0x19, 0xd7, 0x02, 0x25, 0xee, 0xff, 0xa1, 0x19, 0x48, 0x16, 0xc4, 0x49, 0x6a, 0xec, 0xb1, + 0x35, 0xf7, 0xed, 0x02, 0xf9, 0xdc, 0x5a, 0xf6, 0x07, 0x64, 0x0d, 0xe6, 0x02, 0xc9, 0x64, 0x6a, + 0x32, 0x42, 0x1d, 0x09, 0x10, 0xc8, 0x3e, 0x9a, 0xf6, 0x07, 0xe4, 0x09, 0xac, 0x9e, 0xcb, 0x30, + 0x8d, 0x0d, 0x57, 0x63, 0x3b, 0x3b, 0x8c, 0xb8, 0x30, 0x4c, 0xff, 0x1e, 0x18, 0xff, 0x4c, 0x68, + 0xdc, 0x9f, 0x55, 0xea, 0x15, 0x8c, 0x9e, 0x23, 0x1c, 0x67, 0x38, 0xf9, 0x0e, 0x6e, 0x07, 0xf1, + 0x7b, 0xf4, 0x80, 0xfa, 0xd5, 0x12, 0xe7, 0x9a, 0x87, 0xee, 0x5f, 0x15, 0x68, 0x1f, 0xc8, 0x61, + 0x1a, 0x8a, 0x17, 0xe3, 0xc4, 0x7d, 0xb6, 0x5f, 0xf3, 0x51, 0xe6, 0x92, 0x8c, 0x9f, 0xaf, 0xbd, + 0xf9, 0x60, 0xf2, 0xce, 0xbd, 0x22, 0x75, 0x93, 0xcd, 0xb5, 0x5c, 0x69, 0xfb, 0x0e, 0x2e, 0xad, + 0xe4, 0x33, 0x68, 0x46, 0xa8, 0x61, 0x66, 0x9c, 0xe4, 0x7d, 0x00, 0x51, 0xe1, 0xc6, 0x76, 0x76, + 0x9c, 0x46, 0x4c, 0x8e, 0x98, 0x33, 0xba, 0x4f, 0xde, 0xa2, 0x73, 0x71, 0x1a, 0xf5, 0x47, 0xee, + 0x3c, 0xdd, 0x7d, 0x90, 0x8d, 0x90, 0xcc, 0xeb, 0x95, 0x39, 0xd4, 0x80, 0x99, 0xe3, 0x7e, 0xff, + 0xd0, 0x0e, 0xac, 0x3a, 0x54, 0x0f, 0x76, 0xf6, 0xf7, 0x3a, 0x53, 0xdd, 0x10, 0x56, 0x7b, 0x2a, + 0x30, 0xb6, 0xa5, 0x4f, 0xb4, 0x50, 0x3f, 0xca, 0x54, 0xc5, 0x62, 0x9c, 0x4f, 0xef, 0x49, 0x95, + 0xba, 0x0d, 0xb5, 0x7c, 0x3b, 0x4c, 0xbd, 0x67, 0x98, 0x97, 0x7e, 0x75, 0xd0, 0x5c, 0xd0, 0x1d, + 0xc0, 0xad, 0x09, 0xa7, 0xe9, 0xcb, 0x65, 0x51, 0xf5, 0xd3, 0xd7, 0xda, 0xab, 0x60, 0xff, 0x4d, + 0xce, 0xec, 0x7f, 0x47, 0x4b, 0x51, 0xdc, 0xfd, 0xb3, 0x02, 0x0b, 0xef, 0xac, 0x26, 0xe2, 0x41, + 0x2d, 0xcf, 0x5b, 0x05, 0xf3, 0x96, 0xbf, 0xda, 0xe5, 0x92, 0xfd, 0x76, 0x73, 0x17, 0x6a, 0xd1, + 0xe2, 0xdd, 0xd6, 0xbc, 0x1b, 0x89, 0x3c, 0x0c, 0xa5, 0xcf, 0x7c, 0x99, 0xc6, 0x26, 0x6b, 0xb5, + 0x79, 0x04, 0x76, 0xac, 0xbd, 0x67, 0xcd, 0xb6, 0x83, 0xcb, 0x5c, 0x1d, 0xbc, 0xcd, 0xc7, 0x52, + 0xfb, 0x92, 0x7a, 0x1c, 0xbc, 0x15, 0xf6, 0xc7, 0x92, 0xed, 0xc9, 0x33, 0xc1, 0x13, 0x47, 0x73, + 0x1d, 0xd7, 0x8c, 0xf8, 0xc5, 0x0f, 0x82, 0x27, 0x96, 0xb3, 0xbb, 0xfc, 0x4b, 0xb6, 0x8f, 0xb3, + 0x7b, 0x33, 0xfc, 0xbf, 0xf0, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfd, 0xc2, 0xdd, 0xb5, 0x3f, + 0x0c, 0x00, 0x00, } diff --git a/ui/metrics/metrics_proto/metrics.proto b/ui/metrics/metrics_proto/metrics.proto index 3586be01d..44f885977 100644 --- a/ui/metrics/metrics_proto/metrics.proto +++ b/ui/metrics/metrics_proto/metrics.proto @@ -135,8 +135,43 @@ message PerfInfo { // The number of nanoseconds elapsed since start_time. optional uint64 real_time = 4; - // The number of MB for memory use. - optional uint64 memory_use = 5; + // The number of MB for memory use (deprecated as it is too generic). + optional uint64 memory_use = 5 [deprecated=true]; + + // The resource information of each executed process. + repeated ProcessResourceInfo processes_resource_info = 6; +} + +message ProcessResourceInfo { + // The name of the process for identification. + optional string name = 1; + + // The amount of time spent executing in user space in microseconds. + optional uint64 user_time_micros = 2; + + // The amount of time spent executing in kernel mode in microseconds. + optional uint64 system_time_micros = 3; + + // The maximum resident set size memory used in kilobytes. + optional uint64 max_rss_kb = 4; + + // The number of minor page faults serviced without any I/O activity. + optional uint64 minor_page_faults = 5; + + // The number of major page faults serviced that required I/O activity. + optional uint64 major_page_faults = 6; + + // Total IO input in kilobytes. + optional uint64 io_input_kb= 7; + + // Total IO output in kilobytes. + optional uint64 io_output_kb = 8; + + // The number of voluntary context switches + optional uint64 voluntary_context_switches = 9; + + // The number of involuntary context switches + optional uint64 involuntary_context_switches = 10; } message ModuleTypeInfo { diff --git a/ui/status/ninja.go b/ui/status/ninja.go index a11774cce..765679fb2 100644 --- a/ui/status/ninja.go +++ b/ui/status/ninja.go @@ -162,6 +162,17 @@ func (n *NinjaReader) run() { Action: started, Output: msg.EdgeFinished.GetOutput(), Error: err, + Stats: ActionResultStats{ + UserTime: msg.EdgeFinished.GetUserTime(), + SystemTime: msg.EdgeFinished.GetSystemTime(), + MaxRssKB: msg.EdgeFinished.GetMaxRssKb(), + MinorPageFaults: msg.EdgeFinished.GetMinorPageFaults(), + MajorPageFaults: msg.EdgeFinished.GetMajorPageFaults(), + IOInputKB: msg.EdgeFinished.GetIoInputKb(), + IOOutputKB: msg.EdgeFinished.GetIoOutputKb(), + VoluntaryContextSwitches: msg.EdgeFinished.GetVoluntaryContextSwitches(), + InvoluntaryContextSwitches: msg.EdgeFinished.GetInvoluntaryContextSwitches(), + }, }) } } diff --git a/ui/status/ninja_frontend/frontend.pb.go b/ui/status/ninja_frontend/frontend.pb.go index 7ba9de2a9..86e474b62 100644 --- a/ui/status/ninja_frontend/frontend.pb.go +++ b/ui/status/ninja_frontend/frontend.pb.go @@ -371,10 +371,24 @@ type Status_EdgeFinished struct { // Number of milliseconds spent executing in user mode UserTime *uint32 `protobuf:"varint,5,opt,name=user_time,json=userTime" json:"user_time,omitempty"` // Number of milliseconds spent executing in kernel mode - SystemTime *uint32 `protobuf:"varint,6,opt,name=system_time,json=systemTime" json:"system_time,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + SystemTime *uint32 `protobuf:"varint,6,opt,name=system_time,json=systemTime" json:"system_time,omitempty"` + // Max resident set size in kB + MaxRssKb *uint64 `protobuf:"varint,7,opt,name=max_rss_kb,json=maxRssKb" json:"max_rss_kb,omitempty"` + // Minor page faults + MinorPageFaults *uint64 `protobuf:"varint,8,opt,name=minor_page_faults,json=minorPageFaults" json:"minor_page_faults,omitempty"` + // Major page faults + MajorPageFaults *uint64 `protobuf:"varint,9,opt,name=major_page_faults,json=majorPageFaults" json:"major_page_faults,omitempty"` + // IO input in kB + IoInputKb *uint64 `protobuf:"varint,10,opt,name=io_input_kb,json=ioInputKb" json:"io_input_kb,omitempty"` + // IO output in kB + IoOutputKb *uint64 `protobuf:"varint,11,opt,name=io_output_kb,json=ioOutputKb" json:"io_output_kb,omitempty"` + // Voluntary context switches + VoluntaryContextSwitches *uint64 `protobuf:"varint,12,opt,name=voluntary_context_switches,json=voluntaryContextSwitches" json:"voluntary_context_switches,omitempty"` + // Involuntary context switches + InvoluntaryContextSwitches *uint64 `protobuf:"varint,13,opt,name=involuntary_context_switches,json=involuntaryContextSwitches" json:"involuntary_context_switches,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *Status_EdgeFinished) Reset() { *m = Status_EdgeFinished{} } @@ -444,6 +458,55 @@ func (m *Status_EdgeFinished) GetSystemTime() uint32 { return 0 } +func (m *Status_EdgeFinished) GetMaxRssKb() uint64 { + if m != nil && m.MaxRssKb != nil { + return *m.MaxRssKb + } + return 0 +} + +func (m *Status_EdgeFinished) GetMinorPageFaults() uint64 { + if m != nil && m.MinorPageFaults != nil { + return *m.MinorPageFaults + } + return 0 +} + +func (m *Status_EdgeFinished) GetMajorPageFaults() uint64 { + if m != nil && m.MajorPageFaults != nil { + return *m.MajorPageFaults + } + return 0 +} + +func (m *Status_EdgeFinished) GetIoInputKb() uint64 { + if m != nil && m.IoInputKb != nil { + return *m.IoInputKb + } + return 0 +} + +func (m *Status_EdgeFinished) GetIoOutputKb() uint64 { + if m != nil && m.IoOutputKb != nil { + return *m.IoOutputKb + } + return 0 +} + +func (m *Status_EdgeFinished) GetVoluntaryContextSwitches() uint64 { + if m != nil && m.VoluntaryContextSwitches != nil { + return *m.VoluntaryContextSwitches + } + return 0 +} + +func (m *Status_EdgeFinished) GetInvoluntaryContextSwitches() uint64 { + if m != nil && m.InvoluntaryContextSwitches != nil { + return *m.InvoluntaryContextSwitches + } + return 0 +} + type Status_Message struct { // Message priority level (DEBUG, INFO, WARNING, ERROR). Level *Status_Message_Level `protobuf:"varint,1,opt,name=level,enum=ninja.Status_Message_Level,def=0" json:"level,omitempty"` @@ -511,39 +574,48 @@ func init() { } var fileDescriptor_eca3873955a29cfe = []byte{ - // 539 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x54, 0xd1, 0x6e, 0xd3, 0x4a, - 0x10, 0xbd, 0x4e, 0xe2, 0x38, 0x1e, 0x27, 0xb9, 0x61, 0x25, 0x90, 0xeb, 0x0a, 0x35, 0xea, 0x53, - 0x5f, 0x08, 0x12, 0x42, 0x42, 0x20, 0x24, 0x44, 0x44, 0x5a, 0x8a, 0x20, 0x95, 0xb6, 0x45, 0x48, - 0xbc, 0x44, 0x4e, 0x77, 0x5a, 0x8c, 0xec, 0x75, 0xe4, 0xdd, 0x54, 0xe2, 0x37, 0xf8, 0x09, 0xfe, - 0x80, 0xaf, 0xe3, 0x01, 0xed, 0xec, 0xda, 0x75, 0x68, 0xdf, 0x7c, 0x76, 0xce, 0x9c, 0x39, 0x7b, - 0x76, 0x64, 0x18, 0x5f, 0x55, 0xa5, 0xd4, 0x28, 0xc5, 0x6c, 0x53, 0x95, 0xba, 0x64, 0xbe, 0xcc, - 0xe4, 0xf7, 0xf4, 0xf0, 0x4f, 0x00, 0xfd, 0x73, 0x9d, 0xea, 0xad, 0x62, 0x2f, 0x21, 0xd2, 0xa5, - 0x4e, 0xf3, 0x15, 0x8a, 0x6b, 0x54, 0xb1, 0x37, 0xf5, 0x8e, 0xa2, 0x67, 0xf1, 0x8c, 0x78, 0x33, - 0xcb, 0x99, 0x5d, 0x18, 0xc2, 0xc2, 0xd4, 0x39, 0xe8, 0xe6, 0x9b, 0xbd, 0x81, 0xd1, 0x7a, 0x9b, - 0xe5, 0x62, 0xa5, 0x74, 0x5a, 0x69, 0x14, 0x71, 0x87, 0x9a, 0x93, 0xdd, 0xe6, 0xb9, 0xa1, 0x9c, - 0x5b, 0x06, 0x1f, 0xae, 0x5b, 0x88, 0xcd, 0x61, 0x6c, 0x05, 0xae, 0x32, 0x99, 0xa9, 0x6f, 0x28, - 0xe2, 0x2e, 0x29, 0xec, 0xdf, 0xa3, 0x70, 0xec, 0x28, 0xdc, 0xce, 0xac, 0x21, 0x7b, 0x0d, 0x43, - 0xe3, 0xbc, 0xf1, 0xd0, 0x23, 0x85, 0xbd, 0x5d, 0x05, 0xe3, 0xb7, 0xb6, 0x10, 0xe1, 0x2d, 0x30, - 0x57, 0xa0, 0xee, 0xc6, 0x80, 0x7f, 0xdf, 0x15, 0x4c, 0x7b, 0x33, 0x9f, 0xc6, 0x35, 0xe3, 0x9f, - 0x42, 0x50, 0xa0, 0x52, 0xe9, 0x35, 0xc6, 0x7d, 0x6a, 0x7d, 0xb8, 0xdb, 0xfa, 0xc9, 0x16, 0x79, - 0xcd, 0x4a, 0x9e, 0x00, 0xdc, 0xc6, 0xc9, 0x0e, 0xee, 0xa6, 0x3f, 0x6a, 0x67, 0x9c, 0x7c, 0x80, - 0x61, 0x3b, 0x40, 0x36, 0x85, 0x68, 0x93, 0x56, 0x69, 0x9e, 0x63, 0x9e, 0xa9, 0xc2, 0x35, 0xb4, - 0x8f, 0x58, 0x0c, 0xc1, 0x0d, 0x56, 0xeb, 0x52, 0x21, 0xbd, 0xc7, 0x80, 0xd7, 0x30, 0xf9, 0x1f, - 0x46, 0x3b, 0x51, 0x26, 0xbf, 0x3d, 0x88, 0x5a, 0xd1, 0xb0, 0x31, 0x74, 0x32, 0xe1, 0x34, 0x3b, - 0x99, 0x60, 0x8f, 0x01, 0x28, 0xd6, 0x95, 0xce, 0x0a, 0xab, 0x36, 0xe2, 0x21, 0x9d, 0x5c, 0x64, - 0x05, 0xb2, 0x47, 0xd0, 0xcf, 0xe4, 0x66, 0xab, 0x55, 0xdc, 0x9d, 0x76, 0x8f, 0x42, 0xee, 0x90, - 0x71, 0x50, 0x6e, 0x35, 0x15, 0x7a, 0x54, 0xa8, 0x21, 0x63, 0xd0, 0x13, 0xa8, 0x2e, 0x29, 0xe5, - 0x90, 0xd3, 0xb7, 0x61, 0x5f, 0x96, 0x45, 0x91, 0x4a, 0x41, 0x09, 0x86, 0xbc, 0x86, 0xb6, 0x22, - 0x55, 0x99, 0x63, 0x1c, 0xd8, 0x9b, 0x38, 0x98, 0xfc, 0xf2, 0x60, 0xd8, 0x7e, 0x94, 0x3b, 0xce, - 0xf7, 0x60, 0x80, 0x52, 0xb4, 0x7d, 0x07, 0x28, 0x45, 0xed, 0x5a, 0xd1, 0xdb, 0xd0, 0xb2, 0x3d, - 0xe0, 0x0e, 0x99, 0x73, 0x6b, 0x93, 0x56, 0x28, 0xe4, 0x0e, 0xb1, 0x7d, 0x08, 0xb7, 0x0a, 0x2b, - 0xab, 0xe5, 0x93, 0xd6, 0xc0, 0x1c, 0x90, 0xd8, 0x01, 0x44, 0xea, 0x87, 0xd2, 0x58, 0xd8, 0x72, - 0xdf, 0xbe, 0x9f, 0x3d, 0x32, 0x84, 0xe4, 0xa7, 0x07, 0x81, 0xdb, 0x01, 0xf6, 0x02, 0xfc, 0x1c, - 0x6f, 0x30, 0x27, 0x9f, 0xe3, 0x7f, 0xb7, 0xdc, 0xb1, 0x66, 0x1f, 0x0d, 0xe5, 0x55, 0xef, 0x74, - 0x79, 0x7c, 0xc6, 0x2d, 0xdf, 0x04, 0x51, 0x2f, 0x59, 0xc7, 0x46, 0xe4, 0xe0, 0xe1, 0x73, 0xf0, - 0x89, 0xcf, 0x06, 0x40, 0x1d, 0x93, 0xff, 0x58, 0x04, 0xc1, 0x97, 0xb7, 0x7c, 0x79, 0xba, 0x3c, - 0x99, 0x78, 0x2c, 0x04, 0x7f, 0xc1, 0xf9, 0x19, 0x9f, 0x74, 0xcc, 0xe7, 0xbb, 0xc5, 0xfc, 0xf3, - 0xc9, 0xa4, 0x3b, 0x67, 0xef, 0xbb, 0x5f, 0xc7, 0x34, 0x7c, 0x55, 0xff, 0x1f, 0xfe, 0x06, 0x00, - 0x00, 0xff, 0xff, 0xaf, 0x93, 0x48, 0xcf, 0x2a, 0x04, 0x00, 0x00, + // 678 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x94, 0xff, 0x4e, 0xd4, 0x40, + 0x10, 0xc7, 0xbd, 0xdf, 0xd7, 0xe9, 0xdd, 0x71, 0x6c, 0xa2, 0x29, 0x05, 0xe5, 0xc2, 0x5f, 0xc4, + 0xc4, 0x33, 0x31, 0x26, 0x46, 0x43, 0xa2, 0x9e, 0x02, 0x22, 0x0a, 0x66, 0xc1, 0x98, 0xf8, 0x4f, + 0xb3, 0xbd, 0x2e, 0xb0, 0xd8, 0x76, 0x2f, 0xdd, 0x2d, 0xc2, 0x6b, 0xf8, 0x2c, 0xc6, 0xd7, 0xf1, + 0x55, 0xcc, 0xce, 0xb6, 0x47, 0x0f, 0x88, 0xff, 0x75, 0x66, 0x3e, 0xf3, 0x9d, 0xd9, 0x99, 0xed, + 0xc2, 0xe0, 0x24, 0x93, 0xa9, 0xe6, 0x69, 0x34, 0x9e, 0x65, 0x52, 0x4b, 0xd2, 0x4a, 0x45, 0x7a, + 0xce, 0x36, 0x7e, 0x03, 0xb4, 0x8f, 0x34, 0xd3, 0xb9, 0x22, 0x2f, 0xc1, 0xd5, 0x52, 0xb3, 0x38, + 0xe0, 0xd1, 0x29, 0x57, 0x5e, 0x6d, 0x54, 0xdb, 0x74, 0x9f, 0x79, 0x63, 0xe4, 0xc6, 0x96, 0x19, + 0x1f, 0x1b, 0x60, 0xdb, 0xc4, 0x29, 0xe8, 0xf9, 0x37, 0x79, 0x0d, 0xfd, 0x30, 0x17, 0x71, 0x14, + 0x28, 0xcd, 0x32, 0xcd, 0x23, 0xaf, 0x8e, 0xc9, 0xfe, 0x62, 0xf2, 0xc4, 0x20, 0x47, 0x96, 0xa0, + 0xbd, 0xb0, 0x62, 0x91, 0x09, 0x0c, 0xac, 0xc0, 0x89, 0x48, 0x85, 0x3a, 0xe3, 0x91, 0xd7, 0x40, + 0x85, 0xd5, 0x3b, 0x14, 0x76, 0x0a, 0x84, 0xda, 0x9a, 0xa5, 0x49, 0xb6, 0xa0, 0x67, 0x3a, 0x9f, + 0xf7, 0xd0, 0x44, 0x85, 0x95, 0x45, 0x05, 0xd3, 0x6f, 0xd9, 0x82, 0xcb, 0xaf, 0x0d, 0x73, 0x04, + 0xcc, 0x9e, 0x37, 0xd0, 0xba, 0xeb, 0x08, 0x26, 0x7d, 0x5e, 0x1f, 0xcb, 0xcd, 0xcb, 0x3f, 0x85, + 0x4e, 0xc2, 0x95, 0x62, 0xa7, 0xdc, 0x6b, 0x63, 0xea, 0xfd, 0xc5, 0xd4, 0xcf, 0x36, 0x48, 0x4b, + 0xca, 0x7f, 0x02, 0x70, 0x3d, 0x4e, 0xb2, 0x7e, 0x7b, 0xfa, 0xfd, 0xea, 0x8c, 0xfd, 0x8f, 0xd0, + 0xab, 0x0e, 0x90, 0x8c, 0xc0, 0x9d, 0xb1, 0x8c, 0xc5, 0x31, 0x8f, 0x85, 0x4a, 0x8a, 0x84, 0xaa, + 0x8b, 0x78, 0xd0, 0xb9, 0xe0, 0x59, 0x28, 0x15, 0xc7, 0x7d, 0x74, 0x69, 0x69, 0xfa, 0x4b, 0xd0, + 0x5f, 0x18, 0xa5, 0xff, 0xa7, 0x06, 0x6e, 0x65, 0x34, 0x64, 0x00, 0x75, 0x11, 0x15, 0x9a, 0x75, + 0x11, 0x91, 0x87, 0x00, 0x38, 0xd6, 0x40, 0x8b, 0xc4, 0xaa, 0xf5, 0xa9, 0x83, 0x9e, 0x63, 0x91, + 0x70, 0xf2, 0x00, 0xda, 0x22, 0x9d, 0xe5, 0x5a, 0x79, 0x8d, 0x51, 0x63, 0xd3, 0xa1, 0x85, 0x65, + 0x3a, 0x90, 0xb9, 0xc6, 0x40, 0x13, 0x03, 0xa5, 0x49, 0x08, 0x34, 0x23, 0xae, 0xa6, 0x38, 0x65, + 0x87, 0xe2, 0xb7, 0xa1, 0xa7, 0x32, 0x49, 0x58, 0x1a, 0xe1, 0x04, 0x1d, 0x5a, 0x9a, 0x36, 0x92, + 0x2a, 0x19, 0x73, 0xaf, 0x63, 0x4f, 0x52, 0x98, 0xfe, 0xdf, 0x06, 0xf4, 0xaa, 0x4b, 0xb9, 0xd5, + 0xf9, 0x0a, 0x74, 0x79, 0x1a, 0x55, 0xfb, 0xee, 0xf0, 0x34, 0x2a, 0xbb, 0x56, 0xb8, 0x1b, 0xbc, + 0x6c, 0xcb, 0xb4, 0xb0, 0x8c, 0xdf, 0xb6, 0x89, 0x57, 0xc8, 0xa1, 0x85, 0x45, 0x56, 0xc1, 0xc9, + 0x15, 0xcf, 0xac, 0x56, 0x0b, 0xb5, 0xba, 0xc6, 0x81, 0x62, 0xeb, 0xe0, 0xaa, 0x2b, 0xa5, 0x79, + 0x62, 0xc3, 0x6d, 0xbb, 0x3f, 0xeb, 0x42, 0x60, 0x0d, 0x20, 0x61, 0x97, 0x41, 0xa6, 0x54, 0xf0, + 0x23, 0xc4, 0x63, 0x34, 0x69, 0x37, 0x61, 0x97, 0x54, 0xa9, 0xfd, 0x90, 0x3c, 0x86, 0xe5, 0x44, + 0xa4, 0x32, 0x0b, 0x66, 0xcc, 0x5c, 0x42, 0x96, 0xc7, 0x5a, 0x79, 0x5d, 0x84, 0x96, 0x30, 0xf0, + 0x85, 0x9d, 0xf2, 0x1d, 0x74, 0x23, 0xcb, 0xce, 0x6f, 0xb0, 0x4e, 0xc1, 0x9a, 0x40, 0x85, 0x7d, + 0x04, 0xae, 0x90, 0x01, 0xae, 0xc3, 0x94, 0x05, 0xa4, 0x1c, 0x21, 0xf7, 0x8c, 0x67, 0x3f, 0x24, + 0x23, 0xe8, 0x09, 0x19, 0xd8, 0x03, 0x1a, 0xc0, 0x45, 0x00, 0x84, 0x3c, 0x44, 0xd7, 0x7e, 0x48, + 0xb6, 0xc0, 0xbf, 0x90, 0x71, 0x9e, 0x6a, 0x96, 0x5d, 0x05, 0x53, 0xf3, 0x86, 0x5c, 0xea, 0x40, + 0xfd, 0x14, 0x7a, 0x7a, 0xc6, 0x95, 0xd7, 0x43, 0xde, 0x9b, 0x13, 0xef, 0x2c, 0x70, 0x54, 0xc4, + 0xc9, 0x1b, 0x58, 0x13, 0xe9, 0x7f, 0xf2, 0xfb, 0x98, 0xef, 0x57, 0x98, 0x1b, 0x0a, 0xfe, 0xaf, + 0x1a, 0x74, 0x8a, 0x7f, 0x87, 0xbc, 0x80, 0x56, 0xcc, 0x2f, 0x78, 0x8c, 0xfb, 0x1d, 0xdc, 0x7c, + 0x1d, 0x0a, 0x6a, 0xfc, 0xc9, 0x20, 0xaf, 0x9a, 0x7b, 0x07, 0x3b, 0x87, 0xd4, 0xf2, 0xe6, 0x02, + 0x95, 0x3f, 0x67, 0xdd, 0x5e, 0xad, 0xc2, 0xdc, 0x78, 0x0e, 0x2d, 0xe4, 0x49, 0x17, 0x30, 0x63, + 0x78, 0x8f, 0xb8, 0xd0, 0xf9, 0xf6, 0x96, 0x1e, 0xec, 0x1d, 0xec, 0x0e, 0x6b, 0xc4, 0x81, 0xd6, + 0x36, 0xa5, 0x87, 0x74, 0x58, 0x37, 0x9f, 0xef, 0xb7, 0x27, 0x5f, 0x77, 0x87, 0x8d, 0x09, 0xf9, + 0xd0, 0xf8, 0x3e, 0xc0, 0xe2, 0x41, 0xf9, 0xae, 0xfe, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x2f, 0x7a, + 0x33, 0x13, 0x62, 0x05, 0x00, 0x00, } diff --git a/ui/status/ninja_frontend/frontend.proto b/ui/status/ninja_frontend/frontend.proto index baa004668..e5e5d9fd4 100644 --- a/ui/status/ninja_frontend/frontend.proto +++ b/ui/status/ninja_frontend/frontend.proto @@ -65,6 +65,20 @@ message Status { optional uint32 user_time = 5; // Number of milliseconds spent executing in kernel mode optional uint32 system_time = 6; + // Max resident set size in kB + optional uint64 max_rss_kb = 7; + // Minor page faults + optional uint64 minor_page_faults = 8; + // Major page faults + optional uint64 major_page_faults = 9; + // IO input in kB + optional uint64 io_input_kb = 10; + // IO output in kB + optional uint64 io_output_kb = 11; + // Voluntary context switches + optional uint64 voluntary_context_switches = 12; + // Involuntary context switches + optional uint64 involuntary_context_switches = 13; } message Message { diff --git a/ui/status/status.go b/ui/status/status.go index df33baa8b..a5b4a2867 100644 --- a/ui/status/status.go +++ b/ui/status/status.go @@ -54,6 +54,37 @@ type ActionResult struct { // Error is nil if the Action succeeded, or set to an error if it // failed. Error error + + Stats ActionResultStats +} + +type ActionResultStats struct { + // Number of milliseconds spent executing in user mode + UserTime uint32 + + // Number of milliseconds spent executing in kernel mode + SystemTime uint32 + + // Max resident set size in kB + MaxRssKB uint64 + + // Minor page faults + MinorPageFaults uint64 + + // Major page faults + MajorPageFaults uint64 + + // IO input in kB + IOInputKB uint64 + + // IO output in kB + IOOutputKB uint64 + + // Voluntary context switches + VoluntaryContextSwitches uint64 + + // Involuntary context switches + InvoluntaryContextSwitches uint64 } // Counts describes the number of actions in each state diff --git a/ui/tracer/status.go b/ui/tracer/status.go index c83125514..a8b4e62f4 100644 --- a/ui/tracer/status.go +++ b/ui/tracer/status.go @@ -80,9 +80,32 @@ func (s *statusOutput) FinishAction(result status.ActionResult, counts status.Co Dur: uint64(time.Since(start.start).Nanoseconds()) / 1000, Pid: 1, Tid: uint64(start.cpu), + Arg: &statsArg{ + UserTime: result.Stats.UserTime, + SystemTime: result.Stats.SystemTime, + MaxRssKB: result.Stats.MaxRssKB, + MinorPageFaults: result.Stats.MinorPageFaults, + MajorPageFaults: result.Stats.MajorPageFaults, + IOInputKB: result.Stats.IOInputKB, + IOOutputKB: result.Stats.IOOutputKB, + VoluntaryContextSwitches: result.Stats.VoluntaryContextSwitches, + InvoluntaryContextSwitches: result.Stats.InvoluntaryContextSwitches, + }, }) } +type statsArg struct { + UserTime uint32 `json:"user_time"` + SystemTime uint32 `json:"system_time_ms"` + MaxRssKB uint64 `json:"max_rss_kb"` + MinorPageFaults uint64 `json:"minor_page_faults"` + MajorPageFaults uint64 `json:"major_page_faults"` + IOInputKB uint64 `json:"io_input_kb"` + IOOutputKB uint64 `json:"io_output_kb"` + VoluntaryContextSwitches uint64 `json:"voluntary_context_switches"` + InvoluntaryContextSwitches uint64 `json:"involuntary_context_switches"` +} + func (s *statusOutput) Flush() {} func (s *statusOutput) Message(level status.MsgLevel, message string) {} |