Snap for 9679998 from 4cff07db2564cee8fad1145824e6aaf56bcc042b to sdk-release
Change-Id: Iefffe7cb14b96ce4b7c7a2df1152013a132d5268
diff --git a/bootstrap/command.go b/bootstrap/command.go
index 0ddd110..3c41cce 100644
--- a/bootstrap/command.go
+++ b/bootstrap/command.go
@@ -139,17 +139,15 @@
if err := os.WriteFile(joinPath(ctx.SrcDir(), args.OutFile), []byte(nil), outFilePermissions); err != nil {
fatalf("error writing empty Ninja file: %s", err)
}
- }
-
- if !args.EmptyNinjaFile {
+ out = io.Discard.(io.StringWriter)
+ } else {
f, err := os.OpenFile(joinPath(ctx.SrcDir(), args.OutFile), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, outFilePermissions)
if err != nil {
fatalf("error opening Ninja file: %s", err)
}
+ defer f.Close()
buf = bufio.NewWriterSize(f, 16*1024*1024)
out = buf
- } else {
- out = io.Discard.(io.StringWriter)
}
if err := ctx.WriteBuildFile(out); err != nil {
diff --git a/context.go b/context.go
index a7f1013..ddaea4d 100644
--- a/context.go
+++ b/context.go
@@ -50,15 +50,15 @@
// through a series of four phases. Each phase corresponds with a some methods
// on the Context object
//
-// Phase Methods
-// ------------ -------------------------------------------
-// 1. Registration RegisterModuleType, RegisterSingletonType
+// Phase Methods
+// ------------ -------------------------------------------
+// 1. Registration RegisterModuleType, RegisterSingletonType
//
-// 2. Parse ParseBlueprintsFiles, Parse
+// 2. Parse ParseBlueprintsFiles, Parse
//
-// 3. Generate ResolveDependencies, PrepareBuildActions
+// 3. Generate ResolveDependencies, PrepareBuildActions
//
-// 4. Write WriteBuildFile
+// 4. Write WriteBuildFile
//
// The registration phase prepares the context to process Blueprints files
// containing various types of modules. The parse phase reads in one or more
@@ -424,7 +424,7 @@
globs: make(map[globKey]pathtools.GlobResult),
fs: pathtools.OsFs,
finishedMutators: make(map[*mutatorInfo]bool),
- includeTags: &IncludeTags{},
+ includeTags: &IncludeTags{},
outDir: nil,
requiredNinjaMajor: 1,
requiredNinjaMinor: 7,
@@ -481,32 +481,32 @@
//
// As an example, the follow code:
//
-// type myModule struct {
-// properties struct {
-// Foo string
-// Bar []string
-// }
-// }
+// type myModule struct {
+// properties struct {
+// Foo string
+// Bar []string
+// }
+// }
//
-// func NewMyModule() (blueprint.Module, []interface{}) {
-// module := new(myModule)
-// properties := &module.properties
-// return module, []interface{}{properties}
-// }
+// func NewMyModule() (blueprint.Module, []interface{}) {
+// module := new(myModule)
+// properties := &module.properties
+// return module, []interface{}{properties}
+// }
//
-// func main() {
-// ctx := blueprint.NewContext()
-// ctx.RegisterModuleType("my_module", NewMyModule)
-// // ...
-// }
+// func main() {
+// ctx := blueprint.NewContext()
+// ctx.RegisterModuleType("my_module", NewMyModule)
+// // ...
+// }
//
// would support parsing a module defined in a Blueprints file as follows:
//
-// my_module {
-// name: "myName",
-// foo: "my foo string",
-// bar: ["my", "bar", "strings"],
-// }
+// my_module {
+// name: "myName",
+// foo: "my foo string",
+// bar: ["my", "bar", "strings"],
+// }
//
// The factory function may be called from multiple goroutines. Any accesses
// to global variables must be synchronized.
@@ -992,7 +992,6 @@
return true, []error{}
}
-
func (c *Context) ParseFileList(rootDir string, filePaths []string,
config interface{}) (deps []string, errs []error) {
@@ -2821,6 +2820,8 @@
pprof.Do(ctx, pprof.Labels("blueprint", "runMutators"), func(ctx context.Context) {
for _, mutator := range c.mutatorInfo {
pprof.Do(ctx, pprof.Labels("mutator", mutator.name), func(context.Context) {
+ c.BeginEvent(mutator.name)
+ defer c.EndEvent(mutator.name)
var newDeps []string
if mutator.topDownMutator != nil {
newDeps, errs = c.runMutator(config, mutator, topDownMutator)
@@ -3756,32 +3757,30 @@
}
targets := map[string]string{}
-
- // Collect all the module build targets.
- for _, module := range c.moduleInfo {
- for _, buildDef := range module.actionDefs.buildDefs {
+ var collectTargets = func(actionDefs localBuildActions) error {
+ for _, buildDef := range actionDefs.buildDefs {
ruleName := buildDef.Rule.fullName(c.pkgNames)
for _, output := range append(buildDef.Outputs, buildDef.ImplicitOutputs...) {
outputValue, err := output.Eval(c.globalVariables)
if err != nil {
- return nil, err
+ return err
}
targets[outputValue] = ruleName
}
}
+ return nil
+ }
+ // Collect all the module build targets.
+ for _, module := range c.moduleInfo {
+ if err := collectTargets(module.actionDefs); err != nil {
+ return nil, err
+ }
}
// Collect all the singleton build targets.
for _, info := range c.singletonInfo {
- for _, buildDef := range info.actionDefs.buildDefs {
- ruleName := buildDef.Rule.fullName(c.pkgNames)
- for _, output := range append(buildDef.Outputs, buildDef.ImplicitOutputs...) {
- outputValue, err := output.Eval(c.globalVariables)
- if err != nil {
- return nil, err
- }
- targets[outputValue] = ruleName
- }
+ if err := collectTargets(info.actionDefs); err != nil {
+ return nil, err
}
}
@@ -4455,6 +4454,10 @@
return nil
}
+func (c *Context) GetEventHandler() *metrics.EventHandler {
+ return c.EventHandler
+}
+
func (c *Context) BeginEvent(name string) {
c.EventHandler.Begin(name)
}
@@ -4590,7 +4593,7 @@
`
-var moduleHeaderTemplate = `# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+var moduleHeaderTemplate = `# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Module: {{.name}}
Variant: {{.variant}}
Type: {{.typeName}}
@@ -4598,7 +4601,7 @@
Defined: {{.pos}}
`
-var singletonHeaderTemplate = `# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+var singletonHeaderTemplate = `# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Singleton: {{.name}}
Factory: {{.goFactory}}
`
diff --git a/context_test.go b/context_test.go
index 777cfda..40c26c9 100644
--- a/context_test.go
+++ b/context_test.go
@@ -174,11 +174,11 @@
}
}
-// |===B---D - represents a non-walkable edge
-// A = represents a walkable edge
-// |===C===E---G
-// | | A should not be visited because it's the root node.
-// |===F===| B, D and E should not be walked.
+// > |===B---D - represents a non-walkable edge
+// > A = represents a walkable edge
+// > |===C===E---G
+// > | | A should not be visited because it's the root node.
+// > |===F===| B, D and E should not be walked.
func TestWalkDeps(t *testing.T) {
ctx := NewContext()
ctx.MockFileSystem(map[string][]byte{
@@ -187,31 +187,31 @@
name: "A",
deps: ["B", "C"],
}
-
+
bar_module {
name: "B",
deps: ["D"],
}
-
+
foo_module {
name: "C",
deps: ["E", "F"],
}
-
+
foo_module {
name: "D",
}
-
+
bar_module {
name: "E",
deps: ["G"],
}
-
+
foo_module {
name: "F",
deps: ["G"],
}
-
+
foo_module {
name: "G",
}
@@ -249,12 +249,12 @@
}
}
-// |===B---D - represents a non-walkable edge
-// A = represents a walkable edge
-// |===C===E===\ A should not be visited because it's the root node.
-// | | B, D should not be walked.
-// |===F===G===H G should be visited multiple times
-// \===/ H should only be visited once
+// > |===B---D - represents a non-walkable edge
+// > A = represents a walkable edge
+// > |===C===E===\ A should not be visited because it's the root node.
+// > | | B, D should not be walked.
+// > |===F===G===H G should be visited multiple times
+// > \===/ H should only be visited once
func TestWalkDepsDuplicates(t *testing.T) {
ctx := NewContext()
ctx.MockFileSystem(map[string][]byte{
@@ -330,11 +330,11 @@
}
}
-// - represents a non-walkable edge
-// A = represents a walkable edge
-// |===B-------\ A should not be visited because it's the root node.
-// | | B -> D should not be walked.
-// |===C===D===E B -> C -> D -> E should be walked
+// > - represents a non-walkable edge
+// > A = represents a walkable edge
+// > |===B-------\ A should not be visited because it's the root node.
+// > | | B -> D should not be walked.
+// > |===C===D===E B -> C -> D -> E should be walked
func TestWalkDepsDuplicates_IgnoreFirstPath(t *testing.T) {
ctx := NewContext()
ctx.MockFileSystem(map[string][]byte{
@@ -589,7 +589,7 @@
foo_module {
name: "A",
}
-
+
bar_module {
deps: ["A"],
}
@@ -1107,24 +1107,24 @@
"dir1/Android.bp": []byte(dir1_foo_bp),
"dir2/Android.bp": []byte(dir2_foo_bp),
}
- testCases := []struct{
- desc string
+ testCases := []struct {
+ desc string
includeTags []string
expectedDir string
expectedErr string
}{
{
- desc: "use_dir1 is set, use dir1 foo",
+ desc: "use_dir1 is set, use dir1 foo",
includeTags: []string{"use_dir1"},
expectedDir: "dir1",
},
{
- desc: "use_dir2 is set, use dir2 foo",
+ desc: "use_dir2 is set, use dir2 foo",
includeTags: []string{"use_dir2"},
expectedDir: "dir2",
},
{
- desc: "duplicate module error if both use_dir1 and use_dir2 are set",
+ desc: "duplicate module error if both use_dir1 and use_dir2 are set",
includeTags: []string{"use_dir1", "use_dir2"},
expectedDir: "",
expectedErr: `module "foo" already defined`,
diff --git a/doc.go b/doc.go
index 4a9dfd7..9e917f6 100644
--- a/doc.go
+++ b/doc.go
@@ -35,17 +35,17 @@
// the module type looks like a function call, and the properties of the module
// look like optional arguments. For example, a simple module might look like:
//
-// cc_library {
-// name: "cmd",
-// srcs: [
-// "main.c",
-// ],
-// deps: [
-// "libc",
-// ],
-// }
+// cc_library {
+// name: "cmd",
+// srcs: [
+// "main.c",
+// ],
+// deps: [
+// "libc",
+// ],
+// }
//
-// subdirs = ["subdir1", "subdir2"]
+// subdirs = ["subdir1", "subdir2"]
//
// The modules from the top level Blueprints file and recursively through any
// subdirectories listed by the "subdirs" variable are read by Blueprint, and
diff --git a/metrics/Android.bp b/metrics/Android.bp
index 3668668..1e3a6f0 100644
--- a/metrics/Android.bp
+++ b/metrics/Android.bp
@@ -24,4 +24,7 @@
srcs: [
"event_handler.go",
],
+ testSrcs: [
+ "event_handler_test.go",
+ ],
}
diff --git a/metrics/event_handler.go b/metrics/event_handler.go
index 3fd0f37..35a6858 100644
--- a/metrics/event_handler.go
+++ b/metrics/event_handler.go
@@ -56,6 +56,9 @@
// call to End (though other events may begin and end before this event ends).
// Events within the same scope must have unique names.
func (h *EventHandler) Begin(name string) {
+ if strings.ContainsRune(name, '.') {
+ panic(fmt.Sprintf("illegal event name (avoid dot): %s", name))
+ }
h.scopeIds = append(h.scopeIds, name)
h.scopeStartTimes = append(h.scopeStartTimes, _now())
}
@@ -71,7 +74,7 @@
// themselves been marked completed.
func (h *EventHandler) End(name string) {
if len(h.scopeIds) == 0 || name != h.scopeIds[len(h.scopeIds)-1] {
- panic(fmt.Errorf("Unexpected scope end '%s'. Current scope: (%s)",
+ panic(fmt.Errorf("unexpected scope end '%s'. Current scope: (%s)",
name, h.scopeIds))
}
event := Event{
@@ -94,14 +97,14 @@
func (h *EventHandler) CompletedEvents() []Event {
if len(h.scopeIds) > 0 {
panic(fmt.Errorf(
- "Retrieving events before all events have been closed. Current scope: (%s)",
+ "retrieving events before all events have been closed. Current scope: (%s)",
h.scopeIds))
}
// Validate no two events have the same full id.
ids := map[string]struct{}{}
for _, event := range h.completedEvents {
if _, containsId := ids[event.Id]; containsId {
- panic(fmt.Errorf("Duplicate event registered: %s", event.Id))
+ panic(fmt.Errorf("duplicate event registered: %s", event.Id))
}
ids[event.Id] = struct{}{}
}
diff --git a/metrics/event_handler_test.go b/metrics/event_handler_test.go
new file mode 100644
index 0000000..08a59bd
--- /dev/null
+++ b/metrics/event_handler_test.go
@@ -0,0 +1,100 @@
+// Copyright 2022 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package metrics
+
+import (
+ "fmt"
+ "reflect"
+ "strings"
+ "testing"
+)
+
+func Map[A any, B any](in []A, f func(A) B) []B {
+ r := make([]B, len(in))
+ for i, a := range in {
+ r[i] = f(a)
+ }
+ return r
+}
+
+func TestEventNameWithDot(t *testing.T) {
+ defer func() {
+ r := fmt.Sprintf("%v", recover())
+ if !strings.HasPrefix(r, "illegal event name") {
+ t.Errorf("The code did not panic in the expected manner: %s", r)
+ }
+ }()
+ eh := EventHandler{}
+ eh.Begin("a.")
+}
+
+func TestEventNesting(t *testing.T) {
+ eh := EventHandler{}
+ eh.Begin("a")
+ eh.Begin("b")
+ eh.End("b")
+ eh.Begin("c")
+ eh.End("c")
+ eh.End("a")
+ expected := []string{"a.b", "a.c", "a"}
+ actual := Map(eh.CompletedEvents(), func(e Event) string {
+ return e.Id
+ })
+ if !reflect.DeepEqual(expected, actual) {
+ t.Errorf("expected: %s actual %s", expected, actual)
+ }
+}
+
+func TestEventOverlap(t *testing.T) {
+ defer func() {
+ r := fmt.Sprintf("%v", recover())
+ if !strings.Contains(r, "unexpected scope end 'a'") {
+ t.Errorf("expected panic but: %s", r)
+ }
+ }()
+ eh := EventHandler{}
+ eh.Begin("a")
+ eh.Begin("b")
+ eh.End("a")
+}
+
+func TestEventDuplication(t *testing.T) {
+ eh := EventHandler{}
+ eh.Begin("a")
+ eh.Begin("b")
+ eh.End("b")
+ eh.Begin("b")
+ eh.End("b")
+ eh.End("a")
+ defer func() {
+ r := fmt.Sprintf("%v", recover())
+ if !strings.HasPrefix(r, "duplicate event") {
+ t.Errorf("expected panic but: %s", r)
+ }
+ }()
+ eh.CompletedEvents()
+}
+
+func TestIncompleteEvent(t *testing.T) {
+ eh := EventHandler{}
+ eh.Begin("a")
+ defer func() {
+ r := fmt.Sprintf("%v", recover())
+ if !strings.HasPrefix(r, "retrieving events before all events have been closed.") {
+ t.Errorf("expected panic but: %s", r)
+ }
+ }()
+ eh.CompletedEvents()
+}
diff --git a/microfactory/microfactory.go b/microfactory/microfactory.go
index a3c50db..faa0d73 100644
--- a/microfactory/microfactory.go
+++ b/microfactory/microfactory.go
@@ -16,8 +16,8 @@
// to `go install`, but doesn't require a GOPATH. A package->path mapping can
// be specified as command line options:
//
-// -pkg-path android/soong=build/soong
-// -pkg-path github.com/google/blueprint=build/blueprint
+// -pkg-path android/soong=build/soong
+// -pkg-path github.com/google/blueprint=build/blueprint
//
// The paths can be relative to the current working directory, or an absolute
// path. Both packages and paths are compared with full directory names, so the
diff --git a/module_ctx.go b/module_ctx.go
index f2a04c8..841e5c4 100644
--- a/module_ctx.go
+++ b/module_ctx.go
@@ -58,27 +58,27 @@
// that other modules can link against. The library Module might implement the
// following interface:
//
-// type LibraryProducer interface {
-// LibraryFileName() string
-// }
+// type LibraryProducer interface {
+// LibraryFileName() string
+// }
//
-// func IsLibraryProducer(module blueprint.Module) {
-// _, ok := module.(LibraryProducer)
-// return ok
-// }
+// func IsLibraryProducer(module blueprint.Module) {
+// _, ok := module.(LibraryProducer)
+// return ok
+// }
//
// A binary-producing Module that depends on the library Module could then do:
//
-// func (m *myBinaryModule) GenerateBuildActions(ctx blueprint.ModuleContext) {
-// ...
-// var libraryFiles []string
-// ctx.VisitDepsDepthFirstIf(IsLibraryProducer,
-// func(module blueprint.Module) {
-// libProducer := module.(LibraryProducer)
-// libraryFiles = append(libraryFiles, libProducer.LibraryFileName())
-// })
-// ...
-// }
+// func (m *myBinaryModule) GenerateBuildActions(ctx blueprint.ModuleContext) {
+// ...
+// var libraryFiles []string
+// ctx.VisitDepsDepthFirstIf(IsLibraryProducer,
+// func(module blueprint.Module) {
+// libProducer := module.(LibraryProducer)
+// libraryFiles = append(libraryFiles, libProducer.LibraryFileName())
+// })
+// ...
+// }
//
// to build the list of library file names that should be included in its link
// command.
diff --git a/ninja_strings.go b/ninja_strings.go
index 0b783c3..9e83a4d 100644
--- a/ninja_strings.go
+++ b/ninja_strings.go
@@ -325,11 +325,11 @@
return n.variables
}
-func (l literalNinjaString) Value(pkgNames map[*packageContext]string) string {
+func (l literalNinjaString) Value(_ map[*packageContext]string) string {
return defaultEscaper.Replace(string(l))
}
-func (l literalNinjaString) ValueWithEscaper(w io.StringWriter, pkgNames map[*packageContext]string,
+func (l literalNinjaString) ValueWithEscaper(w io.StringWriter, _ map[*packageContext]string,
escaper *strings.Replacer) {
w.WriteString(escaper.Replace(string(l)))
}
diff --git a/package_ctx.go b/package_ctx.go
index 07b7a9c..f8a7cc4 100644
--- a/package_ctx.go
+++ b/package_ctx.go
@@ -31,29 +31,29 @@
// passed to all calls to define module- or singleton-specific Ninja
// definitions. For example:
//
-// package blah
+// package blah
//
-// import (
-// "blueprint"
-// )
+// import (
+// "blueprint"
+// )
//
-// var (
-// pctx = NewPackageContext("path/to/blah")
+// var (
+// pctx = NewPackageContext("path/to/blah")
//
-// myPrivateVar = pctx.StaticVariable("myPrivateVar", "abcdef")
-// MyExportedVar = pctx.StaticVariable("MyExportedVar", "$myPrivateVar 123456!")
+// myPrivateVar = pctx.StaticVariable("myPrivateVar", "abcdef")
+// MyExportedVar = pctx.StaticVariable("MyExportedVar", "$myPrivateVar 123456!")
//
-// SomeRule = pctx.StaticRule(...)
-// )
+// SomeRule = pctx.StaticRule(...)
+// )
//
-// // ...
+// // ...
//
-// func (m *MyModule) GenerateBuildActions(ctx blueprint.Module) {
-// ctx.Build(pctx, blueprint.BuildParams{
-// Rule: SomeRule,
-// Outputs: []string{"$myPrivateVar"},
-// })
-// }
+// func (m *MyModule) GenerateBuildActions(ctx blueprint.Module) {
+// ctx.Build(pctx, blueprint.BuildParams{
+// Rule: SomeRule,
+// Outputs: []string{"$myPrivateVar"},
+// })
+// }
type PackageContext interface {
Import(pkgPath string)
ImportAs(as, pkgPath string)
@@ -190,25 +190,25 @@
// "${pkg.Variable}", while the imported rules can simply be accessed as
// exported Go variables from the package. For example:
//
-// import (
-// "blueprint"
-// "foo/bar"
-// )
+// import (
+// "blueprint"
+// "foo/bar"
+// )
//
-// var pctx = NewPackagePath("blah")
+// var pctx = NewPackagePath("blah")
//
-// func init() {
-// pctx.Import("foo/bar")
-// }
+// func init() {
+// pctx.Import("foo/bar")
+// }
//
-// ...
+// ...
//
-// func (m *MyModule) GenerateBuildActions(ctx blueprint.Module) {
-// ctx.Build(pctx, blueprint.BuildParams{
-// Rule: bar.SomeRule,
-// Outputs: []string{"${bar.SomeVariable}"},
-// })
-// }
+// func (m *MyModule) GenerateBuildActions(ctx blueprint.Module) {
+// ctx.Build(pctx, blueprint.BuildParams{
+// Rule: bar.SomeRule,
+// Outputs: []string{"${bar.SomeVariable}"},
+// })
+// }
//
// Note that the local name used to refer to the package in Ninja variable names
// is derived from pkgPath by extracting the last path component. This differs
diff --git a/pathtools/lists_test.go b/pathtools/lists_test.go
index cce8786..87f24f9 100644
--- a/pathtools/lists_test.go
+++ b/pathtools/lists_test.go
@@ -4,7 +4,7 @@
// 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
+// 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,
diff --git a/proptools/unpack.go b/proptools/unpack.go
index f6d9e95..e1d733c 100644
--- a/proptools/unpack.go
+++ b/proptools/unpack.go
@@ -53,9 +53,13 @@
// If a property a.b.c has a value, a field with the matching name in each runtime value is initialized
// from it. See PropertyNameForField for field and property name matching.
// For instance, if the input contains
-// { foo: "abc", bar: {x: 1},}
+//
+// { foo: "abc", bar: {x: 1},}
+//
// and a runtime value being has been declared as
-// var v struct { Foo string; Bar int }
+//
+// var v struct { Foo string; Bar int }
+//
// then v.Foo will be set to "abc" and v.Bar will be set to 1
// (cf. unpack_test.go for further examples)
//
diff --git a/visit_test.go b/visit_test.go
index 798e289..34e67d1 100644
--- a/visit_test.go
+++ b/visit_test.go
@@ -74,18 +74,18 @@
}
}
-// A
-// |
-// B
-// |\
-// C \
-// \|
-// D
-// |
-// E
-// / \
-// \ /
-// F
+// > A
+// > |
+// > B
+// > |\
+// > C \
+// > \|
+// > D
+// > |
+// > E
+// > / \
+// > \ /
+// > F
func setupVisitTest(t *testing.T) *Context {
ctx := NewContext()
ctx.RegisterModuleType("visit_module", newVisitModule)
@@ -98,22 +98,22 @@
name: "A",
visit: ["B"],
}
-
+
visit_module {
name: "B",
visit: ["C", "D"],
}
-
+
visit_module {
name: "C",
visit: ["D"],
}
-
+
visit_module {
name: "D",
visit: ["E"],
}
-
+
visit_module {
name: "E",
visit: ["F", "F"],