Add Validations support to Blueprint

The Android fork of Ninja supports "validations", a node that is
added to the top level of the build graph whenever another node
is in the build graph.  Add support in Blueprint to specify them
on build statements and write them to the ninja.

Test: ninja_writer_test.go
Change-Id: I87cd1281dbd2ed113cc26a265c50d20c65118c91
This commit is contained in:
Colin Cross 2020-07-09 14:24:56 -07:00
parent e635dc0568
commit 9ece72b055
4 changed files with 26 additions and 5 deletions

View file

@ -68,6 +68,11 @@ func (l *liveTracker) AddBuildDefDeps(def *buildDef) error {
return err return err
} }
err = l.addNinjaStringListDeps(def.Validations)
if err != nil {
return err
}
for _, value := range def.Variables { for _, value := range def.Variables {
err = l.addNinjaStringDeps(value) err = l.addNinjaStringDeps(value)
if err != nil { if err != nil {

View file

@ -87,6 +87,7 @@ type BuildParams struct {
Inputs []string // The list of explicit input dependencies. Inputs []string // The list of explicit input dependencies.
Implicits []string // The list of implicit input dependencies. Implicits []string // The list of implicit input dependencies.
OrderOnly []string // The list of order-only dependencies. OrderOnly []string // The list of order-only dependencies.
Validations []string // The list of validations to run when this rule runs.
Args map[string]string // The variable/value pairs to set. Args map[string]string // The variable/value pairs to set.
Optional bool // Skip outputting a default statement Optional bool // Skip outputting a default statement
} }
@ -257,6 +258,7 @@ type buildDef struct {
Inputs []ninjaString Inputs []ninjaString
Implicits []ninjaString Implicits []ninjaString
OrderOnly []ninjaString OrderOnly []ninjaString
Validations []ninjaString
Args map[Variable]ninjaString Args map[Variable]ninjaString
Variables map[string]ninjaString Variables map[string]ninjaString
Optional bool Optional bool
@ -314,6 +316,11 @@ func parseBuildParams(scope scope, params *BuildParams) (*buildDef,
return nil, fmt.Errorf("error parsing OrderOnly param: %s", err) return nil, fmt.Errorf("error parsing OrderOnly param: %s", err)
} }
b.Validations, err = parseNinjaStrings(scope, params.Validations)
if err != nil {
return nil, fmt.Errorf("error parsing Validations param: %s", err)
}
b.Optional = params.Optional b.Optional = params.Optional
if params.Depfile != "" { if params.Depfile != "" {
@ -373,6 +380,7 @@ func (b *buildDef) WriteTo(nw *ninjaWriter, pkgNames map[*packageContext]string)
explicitDeps = valueList(b.Inputs, pkgNames, inputEscaper) explicitDeps = valueList(b.Inputs, pkgNames, inputEscaper)
implicitDeps = valueList(b.Implicits, pkgNames, inputEscaper) implicitDeps = valueList(b.Implicits, pkgNames, inputEscaper)
orderOnlyDeps = valueList(b.OrderOnly, pkgNames, inputEscaper) orderOnlyDeps = valueList(b.OrderOnly, pkgNames, inputEscaper)
validations = valueList(b.Validations, pkgNames, inputEscaper)
) )
if b.RuleDef != nil { if b.RuleDef != nil {
@ -380,7 +388,7 @@ func (b *buildDef) WriteTo(nw *ninjaWriter, pkgNames map[*packageContext]string)
orderOnlyDeps = append(valueList(b.RuleDef.CommandOrderOnly, pkgNames, inputEscaper), orderOnlyDeps...) orderOnlyDeps = append(valueList(b.RuleDef.CommandOrderOnly, pkgNames, inputEscaper), orderOnlyDeps...)
} }
err := nw.Build(comment, rule, outputs, implicitOuts, explicitDeps, implicitDeps, orderOnlyDeps) err := nw.Build(comment, rule, outputs, implicitOuts, explicitDeps, implicitDeps, orderOnlyDeps, validations)
if err != nil { if err != nil {
return err return err
} }

View file

@ -104,7 +104,7 @@ func (n *ninjaWriter) Rule(name string) error {
} }
func (n *ninjaWriter) Build(comment string, rule string, outputs, implicitOuts, func (n *ninjaWriter) Build(comment string, rule string, outputs, implicitOuts,
explicitDeps, implicitDeps, orderOnlyDeps []string) error { explicitDeps, implicitDeps, orderOnlyDeps, validations []string) error {
n.justDidBlankLine = false n.justDidBlankLine = false
@ -161,6 +161,14 @@ func (n *ninjaWriter) Build(comment string, rule string, outputs, implicitOuts,
} }
} }
if len(validations) > 0 {
wrapper.WriteStringWithSpace("|@")
for _, dep := range validations {
wrapper.WriteStringWithSpace(dep)
}
}
return wrapper.Flush() return wrapper.Flush()
} }

View file

@ -50,9 +50,9 @@ var ninjaWriterTestCases = []struct {
{ {
input: func(w *ninjaWriter) { input: func(w *ninjaWriter) {
ck(w.Build("foo comment", "foo", []string{"o1", "o2"}, []string{"io1", "io2"}, ck(w.Build("foo comment", "foo", []string{"o1", "o2"}, []string{"io1", "io2"},
[]string{"e1", "e2"}, []string{"i1", "i2"}, []string{"oo1", "oo2"})) []string{"e1", "e2"}, []string{"i1", "i2"}, []string{"oo1", "oo2"}, []string{"v1", "v2"}))
}, },
output: "# foo comment\nbuild o1 o2 | io1 io2: foo e1 e2 | i1 i2 || oo1 oo2\n", output: "# foo comment\nbuild o1 o2 | io1 io2: foo e1 e2 | i1 i2 || oo1 oo2 |@ v1 v2\n",
}, },
{ {
input: func(w *ninjaWriter) { input: func(w *ninjaWriter) {
@ -94,7 +94,7 @@ var ninjaWriterTestCases = []struct {
ck(w.ScopedAssign("command", "echo out: $out in: $in _arg: $_arg")) ck(w.ScopedAssign("command", "echo out: $out in: $in _arg: $_arg"))
ck(w.ScopedAssign("pool", "p")) ck(w.ScopedAssign("pool", "p"))
ck(w.BlankLine()) ck(w.BlankLine())
ck(w.Build("r comment", "r", []string{"foo.o"}, nil, []string{"foo.in"}, nil, nil)) ck(w.Build("r comment", "r", []string{"foo.o"}, nil, []string{"foo.in"}, nil, nil, nil))
ck(w.ScopedAssign("_arg", "arg value")) ck(w.ScopedAssign("_arg", "arg value"))
}, },
output: `pool p output: `pool p