Move name memoization out of variables am: 6bc984abca
Original change: https://android-review.googlesource.com/c/platform/build/blueprint/+/2917001 Change-Id: I240b9a3db493a0114c53195e99721644586184da Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
commit
c0b0a19454
7 changed files with 141 additions and 185 deletions
128
context.go
128
context.go
|
@ -16,6 +16,7 @@ package blueprint
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"cmp"
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
|
@ -29,6 +30,7 @@ import (
|
|||
"reflect"
|
||||
"runtime"
|
||||
"runtime/pprof"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
@ -100,7 +102,7 @@ type Context struct {
|
|||
allowMissingDependencies bool
|
||||
|
||||
// set during PrepareBuildActions
|
||||
pkgNames map[*packageContext]string
|
||||
nameTracker *nameTracker
|
||||
liveGlobals *liveTracker
|
||||
globalVariables map[Variable]*ninjaString
|
||||
globalPools map[Pool]*poolDef
|
||||
|
@ -2741,7 +2743,7 @@ func jsonModuleFromModuleInfo(m *moduleInfo) *JsonModule {
|
|||
return result
|
||||
}
|
||||
|
||||
func jsonModuleWithActionsFromModuleInfo(m *moduleInfo) *JsonModule {
|
||||
func jsonModuleWithActionsFromModuleInfo(m *moduleInfo, nameTracker *nameTracker) *JsonModule {
|
||||
result := &JsonModule{
|
||||
jsonModuleName: jsonModuleName{
|
||||
Name: m.Name(),
|
||||
|
@ -2758,17 +2760,17 @@ func jsonModuleWithActionsFromModuleInfo(m *moduleInfo) *JsonModule {
|
|||
Inputs: append(append(append(
|
||||
bDef.InputStrings,
|
||||
bDef.ImplicitStrings...),
|
||||
getNinjaStringsWithNilPkgNames(bDef.Inputs)...),
|
||||
getNinjaStringsWithNilPkgNames(bDef.Implicits)...),
|
||||
getNinjaStrings(bDef.Inputs, nameTracker)...),
|
||||
getNinjaStrings(bDef.Implicits, nameTracker)...),
|
||||
|
||||
Outputs: append(append(append(
|
||||
bDef.OutputStrings,
|
||||
bDef.ImplicitOutputStrings...),
|
||||
getNinjaStringsWithNilPkgNames(bDef.Outputs)...),
|
||||
getNinjaStringsWithNilPkgNames(bDef.ImplicitOutputs)...),
|
||||
getNinjaStrings(bDef.Outputs, nameTracker)...),
|
||||
getNinjaStrings(bDef.ImplicitOutputs, nameTracker)...),
|
||||
}
|
||||
if d, ok := bDef.Variables["description"]; ok {
|
||||
a.Desc = d.Value(nil)
|
||||
a.Desc = d.Value(nameTracker)
|
||||
}
|
||||
actions = append(actions, a)
|
||||
}
|
||||
|
@ -2786,12 +2788,11 @@ func jsonModuleWithActionsFromModuleInfo(m *moduleInfo) *JsonModule {
|
|||
return result
|
||||
}
|
||||
|
||||
// Gets a list of strings from the given list of ninjaStrings by invoking ninjaString.Value with
|
||||
// nil pkgNames on each of the input ninjaStrings.
|
||||
func getNinjaStringsWithNilPkgNames(nStrs []*ninjaString) []string {
|
||||
// Gets a list of strings from the given list of ninjaStrings by invoking ninjaString.Value on each.
|
||||
func getNinjaStrings(nStrs []*ninjaString, nameTracker *nameTracker) []string {
|
||||
var strs []string
|
||||
for _, nstr := range nStrs {
|
||||
strs = append(strs, nstr.Value(nil))
|
||||
strs = append(strs, nstr.Value(nameTracker))
|
||||
}
|
||||
return strs
|
||||
}
|
||||
|
@ -2799,7 +2800,7 @@ func getNinjaStringsWithNilPkgNames(nStrs []*ninjaString) []string {
|
|||
func (c *Context) GetWeightedOutputsFromPredicate(predicate func(*JsonModule) (bool, int)) map[string]int {
|
||||
outputToWeight := make(map[string]int)
|
||||
for _, m := range c.modulesSorted {
|
||||
jmWithActions := jsonModuleWithActionsFromModuleInfo(m)
|
||||
jmWithActions := jsonModuleWithActionsFromModuleInfo(m, c.nameTracker)
|
||||
if ok, weight := predicate(jmWithActions); ok {
|
||||
for _, a := range jmWithActions.Module["Actions"].([]JSONAction) {
|
||||
for _, o := range a.Outputs {
|
||||
|
@ -2831,7 +2832,7 @@ func (c *Context) PrintJSONGraphAndActions(wGraph io.Writer, wActions io.Writer)
|
|||
modulesToActions := make([]*JsonModule, 0)
|
||||
for _, m := range c.modulesSorted {
|
||||
jm := jsonModuleFromModuleInfo(m)
|
||||
jmWithActions := jsonModuleWithActionsFromModuleInfo(m)
|
||||
jmWithActions := jsonModuleWithActionsFromModuleInfo(m, c.nameTracker)
|
||||
for _, d := range m.directDeps {
|
||||
jm.Deps = append(jm.Deps, jsonDep{
|
||||
jsonModuleName: *jsonModuleNameFromModuleInfo(d.module),
|
||||
|
@ -2918,12 +2919,12 @@ func (c *Context) PrepareBuildActions(config interface{}) (deps []string, errs [
|
|||
|
||||
deps = append(deps, depsPackages...)
|
||||
|
||||
c.memoizeFullNames(c.liveGlobals, pkgNames)
|
||||
nameTracker := c.memoizeFullNames(c.liveGlobals, pkgNames)
|
||||
|
||||
// This will panic if it finds a problem since it's a programming error.
|
||||
c.checkForVariableReferenceCycles(c.liveGlobals.variables, pkgNames)
|
||||
c.checkForVariableReferenceCycles(c.liveGlobals.variables, nameTracker)
|
||||
|
||||
c.pkgNames = pkgNames
|
||||
c.nameTracker = nameTracker
|
||||
c.globalVariables = c.liveGlobals.variables
|
||||
c.globalPools = c.liveGlobals.pools
|
||||
c.globalRules = c.liveGlobals.rules
|
||||
|
@ -3862,20 +3863,27 @@ func (c *Context) makeUniquePackageNames(
|
|||
// memoizeFullNames stores the full name of each live global variable, rule and pool since each is
|
||||
// guaranteed to be used at least twice, once in the definition and once for each usage, and many
|
||||
// are used much more than once.
|
||||
func (c *Context) memoizeFullNames(liveGlobals *liveTracker, pkgNames map[*packageContext]string) {
|
||||
func (c *Context) memoizeFullNames(liveGlobals *liveTracker, pkgNames map[*packageContext]string) *nameTracker {
|
||||
nameTracker := &nameTracker{
|
||||
pkgNames: pkgNames,
|
||||
variables: make(map[Variable]string),
|
||||
rules: make(map[Rule]string),
|
||||
pools: make(map[Pool]string),
|
||||
}
|
||||
for v := range liveGlobals.variables {
|
||||
v.memoizeFullName(pkgNames)
|
||||
nameTracker.variables[v] = v.fullName(pkgNames)
|
||||
}
|
||||
for r := range liveGlobals.rules {
|
||||
r.memoizeFullName(pkgNames)
|
||||
nameTracker.rules[r] = r.fullName(pkgNames)
|
||||
}
|
||||
for p := range liveGlobals.pools {
|
||||
p.memoizeFullName(pkgNames)
|
||||
nameTracker.pools[p] = p.fullName(pkgNames)
|
||||
}
|
||||
return nameTracker
|
||||
}
|
||||
|
||||
func (c *Context) checkForVariableReferenceCycles(
|
||||
variables map[Variable]*ninjaString, pkgNames map[*packageContext]string) {
|
||||
variables map[Variable]*ninjaString, nameTracker *nameTracker) {
|
||||
|
||||
visited := make(map[Variable]bool) // variables that were already checked
|
||||
checking := make(map[Variable]bool) // variables actively being checked
|
||||
|
@ -3905,12 +3913,12 @@ func (c *Context) checkForVariableReferenceCycles(
|
|||
msgs := []string{"detected variable reference cycle:"}
|
||||
|
||||
// Iterate backwards through the cycle list.
|
||||
curName := v.fullName(pkgNames)
|
||||
curValue := value.Value(pkgNames)
|
||||
curName := nameTracker.Variable(v)
|
||||
curValue := value.Value(nameTracker)
|
||||
for i := len(cycle) - 1; i >= 0; i-- {
|
||||
next := cycle[i]
|
||||
nextName := next.fullName(pkgNames)
|
||||
nextValue := variables[next].Value(pkgNames)
|
||||
nextName := nameTracker.Variable(next)
|
||||
nextValue := variables[next].Value(nameTracker)
|
||||
|
||||
msgs = append(msgs, fmt.Sprintf(
|
||||
" %q depends on %q", curName, nextName))
|
||||
|
@ -3958,7 +3966,7 @@ func (c *Context) AllTargets() (map[string]string, error) {
|
|||
targets := map[string]string{}
|
||||
var collectTargets = func(actionDefs localBuildActions) error {
|
||||
for _, buildDef := range actionDefs.buildDefs {
|
||||
ruleName := buildDef.Rule.fullName(c.pkgNames)
|
||||
ruleName := c.nameTracker.Rule(buildDef.Rule)
|
||||
for _, output := range append(buildDef.Outputs, buildDef.ImplicitOutputs...) {
|
||||
outputValue, err := output.Eval(c.globalVariables)
|
||||
if err != nil {
|
||||
|
@ -4266,7 +4274,7 @@ func (c *Context) writeBuildFileHeader(nw *ninjaWriter) error {
|
|||
|
||||
var pkgs []pkgAssociation
|
||||
maxNameLen := 0
|
||||
for pkg, name := range c.pkgNames {
|
||||
for pkg, name := range c.nameTracker.pkgNames {
|
||||
pkgs = append(pkgs, pkgAssociation{
|
||||
PkgName: name,
|
||||
PkgPath: pkg.pkgPath,
|
||||
|
@ -4319,7 +4327,7 @@ func (c *Context) writeSubninjas(nw *ninjaWriter) error {
|
|||
|
||||
func (c *Context) writeBuildDir(nw *ninjaWriter) error {
|
||||
if c.outDir != nil {
|
||||
err := nw.Assign("builddir", c.outDir.Value(c.pkgNames))
|
||||
err := nw.Assign("builddir", c.outDir.Value(c.nameTracker))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -4332,29 +4340,6 @@ func (c *Context) writeBuildDir(nw *ninjaWriter) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
type globalEntity interface {
|
||||
fullName(pkgNames map[*packageContext]string) string
|
||||
}
|
||||
|
||||
type globalEntitySorter struct {
|
||||
pkgNames map[*packageContext]string
|
||||
entities []globalEntity
|
||||
}
|
||||
|
||||
func (s *globalEntitySorter) Len() int {
|
||||
return len(s.entities)
|
||||
}
|
||||
|
||||
func (s *globalEntitySorter) Less(i, j int) bool {
|
||||
iName := s.entities[i].fullName(s.pkgNames)
|
||||
jName := s.entities[j].fullName(s.pkgNames)
|
||||
return iName < jName
|
||||
}
|
||||
|
||||
func (s *globalEntitySorter) Swap(i, j int) {
|
||||
s.entities[i], s.entities[j] = s.entities[j], s.entities[i]
|
||||
}
|
||||
|
||||
func (c *Context) writeGlobalVariables(nw *ninjaWriter) error {
|
||||
visited := make(map[Variable]bool)
|
||||
|
||||
|
@ -4373,7 +4358,7 @@ func (c *Context) writeGlobalVariables(nw *ninjaWriter) error {
|
|||
}
|
||||
}
|
||||
|
||||
err := nw.Assign(v.fullName(c.pkgNames), value.Value(c.pkgNames))
|
||||
err := nw.Assign(c.nameTracker.Variable(v), value.Value(c.nameTracker))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -4386,15 +4371,16 @@ func (c *Context) writeGlobalVariables(nw *ninjaWriter) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
globalVariables := make([]globalEntity, 0, len(c.globalVariables))
|
||||
globalVariables := make([]Variable, 0, len(c.globalVariables))
|
||||
for variable := range c.globalVariables {
|
||||
globalVariables = append(globalVariables, variable)
|
||||
}
|
||||
|
||||
sort.Sort(&globalEntitySorter{c.pkgNames, globalVariables})
|
||||
slices.SortFunc(globalVariables, func(a, b Variable) int {
|
||||
return cmp.Compare(c.nameTracker.Variable(a), c.nameTracker.Variable(b))
|
||||
})
|
||||
|
||||
for _, entity := range globalVariables {
|
||||
v := entity.(Variable)
|
||||
for _, v := range globalVariables {
|
||||
if !visited[v] {
|
||||
err := walk(v)
|
||||
if err != nil {
|
||||
|
@ -4407,16 +4393,17 @@ func (c *Context) writeGlobalVariables(nw *ninjaWriter) error {
|
|||
}
|
||||
|
||||
func (c *Context) writeGlobalPools(nw *ninjaWriter) error {
|
||||
globalPools := make([]globalEntity, 0, len(c.globalPools))
|
||||
globalPools := make([]Pool, 0, len(c.globalPools))
|
||||
for pool := range c.globalPools {
|
||||
globalPools = append(globalPools, pool)
|
||||
}
|
||||
|
||||
sort.Sort(&globalEntitySorter{c.pkgNames, globalPools})
|
||||
slices.SortFunc(globalPools, func(a, b Pool) int {
|
||||
return cmp.Compare(c.nameTracker.Pool(a), c.nameTracker.Pool(b))
|
||||
})
|
||||
|
||||
for _, entity := range globalPools {
|
||||
pool := entity.(Pool)
|
||||
name := pool.fullName(c.pkgNames)
|
||||
for _, pool := range globalPools {
|
||||
name := c.nameTracker.Pool(pool)
|
||||
def := c.globalPools[pool]
|
||||
err := def.WriteTo(nw, name)
|
||||
if err != nil {
|
||||
|
@ -4433,18 +4420,19 @@ func (c *Context) writeGlobalPools(nw *ninjaWriter) error {
|
|||
}
|
||||
|
||||
func (c *Context) writeGlobalRules(nw *ninjaWriter) error {
|
||||
globalRules := make([]globalEntity, 0, len(c.globalRules))
|
||||
globalRules := make([]Rule, 0, len(c.globalRules))
|
||||
for rule := range c.globalRules {
|
||||
globalRules = append(globalRules, rule)
|
||||
}
|
||||
|
||||
sort.Sort(&globalEntitySorter{c.pkgNames, globalRules})
|
||||
slices.SortFunc(globalRules, func(a, b Rule) int {
|
||||
return cmp.Compare(c.nameTracker.Rule(a), c.nameTracker.Rule(b))
|
||||
})
|
||||
|
||||
for _, entity := range globalRules {
|
||||
rule := entity.(Rule)
|
||||
name := rule.fullName(c.pkgNames)
|
||||
for _, rule := range globalRules {
|
||||
name := c.nameTracker.Rule(rule)
|
||||
def := c.globalRules[rule]
|
||||
err := def.WriteTo(nw, name, c.pkgNames)
|
||||
err := def.WriteTo(nw, name, c.nameTracker)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -4766,7 +4754,7 @@ func (c *Context) writeLocalBuildActions(nw *ninjaWriter,
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = nw.Assign(name, value.Value(c.pkgNames))
|
||||
err = nw.Assign(name, value.Value(c.nameTracker))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -4789,7 +4777,7 @@ func (c *Context) writeLocalBuildActions(nw *ninjaWriter,
|
|||
panic(err)
|
||||
}
|
||||
|
||||
err = def.WriteTo(nw, name, c.pkgNames)
|
||||
err = def.WriteTo(nw, name, c.nameTracker)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -4802,7 +4790,7 @@ func (c *Context) writeLocalBuildActions(nw *ninjaWriter,
|
|||
|
||||
// Write the build definitions.
|
||||
for _, buildDef := range defs.buildDefs {
|
||||
err := buildDef.WriteTo(nw, c.pkgNames)
|
||||
err := buildDef.WriteTo(nw, c.nameTracker)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -229,8 +229,7 @@ func parseRuleParams(scope scope, params *RuleParams) (*ruleDef,
|
|||
return r, nil
|
||||
}
|
||||
|
||||
func (r *ruleDef) WriteTo(nw *ninjaWriter, name string,
|
||||
pkgNames map[*packageContext]string) error {
|
||||
func (r *ruleDef) WriteTo(nw *ninjaWriter, name string, nameTracker *nameTracker) error {
|
||||
|
||||
if r.Comment != "" {
|
||||
err := nw.Comment(r.Comment)
|
||||
|
@ -245,13 +244,13 @@ func (r *ruleDef) WriteTo(nw *ninjaWriter, name string,
|
|||
}
|
||||
|
||||
if r.Pool != nil {
|
||||
err = nw.ScopedAssign("pool", r.Pool.fullName(pkgNames))
|
||||
err = nw.ScopedAssign("pool", nameTracker.Pool(r.Pool))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = writeVariables(nw, r.Variables, pkgNames)
|
||||
err = writeVariables(nw, r.Variables, nameTracker)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -415,10 +414,10 @@ func parseBuildParams(scope scope, params *BuildParams,
|
|||
return b, nil
|
||||
}
|
||||
|
||||
func (b *buildDef) WriteTo(nw *ninjaWriter, pkgNames map[*packageContext]string) error {
|
||||
func (b *buildDef) WriteTo(nw *ninjaWriter, nameTracker *nameTracker) error {
|
||||
var (
|
||||
comment = b.Comment
|
||||
rule = b.Rule.fullName(pkgNames)
|
||||
rule = nameTracker.Rule(b.Rule)
|
||||
outputs = b.Outputs
|
||||
implicitOuts = b.ImplicitOutputs
|
||||
explicitDeps = b.Inputs
|
||||
|
@ -441,12 +440,12 @@ func (b *buildDef) WriteTo(nw *ninjaWriter, pkgNames map[*packageContext]string)
|
|||
err := nw.Build(comment, rule, outputs, implicitOuts, explicitDeps, implicitDeps, orderOnlyDeps, validations,
|
||||
outputStrings, implicitOutStrings, explicitDepStrings,
|
||||
implicitDepStrings, orderOnlyDepStrings, validationStrings,
|
||||
pkgNames)
|
||||
nameTracker)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = writeVariables(nw, b.Variables, pkgNames)
|
||||
err = writeVariables(nw, b.Variables, nameTracker)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -458,8 +457,8 @@ func (b *buildDef) WriteTo(nw *ninjaWriter, pkgNames map[*packageContext]string)
|
|||
args := make([]nameValuePair, 0, len(b.Args))
|
||||
|
||||
for argVar, value := range b.Args {
|
||||
fullName := argVar.fullName(pkgNames)
|
||||
args = append(args, nameValuePair{fullName, value.Value(pkgNames)})
|
||||
fullName := nameTracker.Variable(argVar)
|
||||
args = append(args, nameValuePair{fullName, value.Value(nameTracker)})
|
||||
}
|
||||
sort.Slice(args, func(i, j int) bool { return args[i].name < args[j].name })
|
||||
|
||||
|
@ -471,7 +470,7 @@ func (b *buildDef) WriteTo(nw *ninjaWriter, pkgNames map[*packageContext]string)
|
|||
}
|
||||
|
||||
if !b.Optional {
|
||||
err = nw.Default(pkgNames, outputs, outputStrings)
|
||||
err = nw.Default(nameTracker, outputs, outputStrings)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -480,8 +479,7 @@ func (b *buildDef) WriteTo(nw *ninjaWriter, pkgNames map[*packageContext]string)
|
|||
return nw.BlankLine()
|
||||
}
|
||||
|
||||
func writeVariables(nw *ninjaWriter, variables map[string]*ninjaString,
|
||||
pkgNames map[*packageContext]string) error {
|
||||
func writeVariables(nw *ninjaWriter, variables map[string]*ninjaString, nameTracker *nameTracker) error {
|
||||
var keys []string
|
||||
for k := range variables {
|
||||
keys = append(keys, k)
|
||||
|
@ -489,7 +487,7 @@ func writeVariables(nw *ninjaWriter, variables map[string]*ninjaString,
|
|||
sort.Strings(keys)
|
||||
|
||||
for _, name := range keys {
|
||||
err := nw.ScopedAssign(name, variables[name].Value(pkgNames))
|
||||
err := nw.ScopedAssign(name, variables[name].Value(nameTracker))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -324,17 +324,16 @@ func parseNinjaOrSimpleStrings(scope scope, strs []string) ([]*ninjaString, []st
|
|||
return ninjaStrings, simpleStrings, nil
|
||||
}
|
||||
|
||||
func (n *ninjaString) Value(pkgNames map[*packageContext]string) string {
|
||||
func (n *ninjaString) Value(nameTracker *nameTracker) string {
|
||||
if n.variables == nil || len(*n.variables) == 0 {
|
||||
return defaultEscaper.Replace(n.str)
|
||||
}
|
||||
str := &strings.Builder{}
|
||||
n.ValueWithEscaper(str, pkgNames, defaultEscaper)
|
||||
n.ValueWithEscaper(str, nameTracker, defaultEscaper)
|
||||
return str.String()
|
||||
}
|
||||
|
||||
func (n *ninjaString) ValueWithEscaper(w io.StringWriter, pkgNames map[*packageContext]string,
|
||||
escaper *strings.Replacer) {
|
||||
func (n *ninjaString) ValueWithEscaper(w io.StringWriter, nameTracker *nameTracker, escaper *strings.Replacer) {
|
||||
|
||||
if n.variables == nil || len(*n.variables) == 0 {
|
||||
w.WriteString(escaper.Replace(n.str))
|
||||
|
@ -348,7 +347,7 @@ func (n *ninjaString) ValueWithEscaper(w io.StringWriter, pkgNames map[*packageC
|
|||
w.WriteString("$ ")
|
||||
} else {
|
||||
w.WriteString("${")
|
||||
w.WriteString(v.variable.fullName(pkgNames))
|
||||
w.WriteString(nameTracker.Variable(v.variable))
|
||||
w.WriteString("}")
|
||||
}
|
||||
i = int(v.end)
|
||||
|
|
|
@ -164,7 +164,7 @@ func TestParseNinjaString(t *testing.T) {
|
|||
|
||||
output, err := parseNinjaString(scope, testCase.input)
|
||||
if err == nil {
|
||||
if g, w := output.Value(nil), testCase.value; g != w {
|
||||
if g, w := output.Value(&nameTracker{}), testCase.value; g != w {
|
||||
t.Errorf("incorrect Value output, want %q, got %q", w, g)
|
||||
}
|
||||
|
||||
|
@ -191,7 +191,11 @@ func TestParseNinjaString(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestParseNinjaStringWithImportedVar(t *testing.T) {
|
||||
ImpVar := &staticVariable{name_: "ImpVar", fullName_: "g.impPkg.ImpVar"}
|
||||
pctx := &packageContext{}
|
||||
pkgNames := map[*packageContext]string{
|
||||
pctx: "impPkg",
|
||||
}
|
||||
ImpVar := &staticVariable{pctx: pctx, name_: "ImpVar"}
|
||||
impScope := newScope(nil)
|
||||
impScope.AddVariable(ImpVar)
|
||||
scope := newScope(nil)
|
||||
|
@ -211,7 +215,7 @@ func TestParseNinjaStringWithImportedVar(t *testing.T) {
|
|||
t.Errorf(" got: %#v", *output.variables)
|
||||
}
|
||||
|
||||
if g, w := output.Value(nil), "abc def ${g.impPkg.ImpVar} ghi"; g != w {
|
||||
if g, w := output.Value(&nameTracker{pkgNames: pkgNames}), "abc def ${g.impPkg.ImpVar} ghi"; g != w {
|
||||
t.Errorf("incorrect Value output, want %q got %q", w, g)
|
||||
}
|
||||
}
|
||||
|
@ -289,7 +293,7 @@ func Test_parseNinjaOrSimpleStrings(t *testing.T) {
|
|||
if gotNinjaStrings != nil {
|
||||
evaluatedNinjaStrings = make([]string, 0, len(gotNinjaStrings))
|
||||
for _, ns := range gotNinjaStrings {
|
||||
evaluatedNinjaStrings = append(evaluatedNinjaStrings, ns.Value(nil))
|
||||
evaluatedNinjaStrings = append(evaluatedNinjaStrings, ns.Value(&nameTracker{}))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -364,7 +368,7 @@ func BenchmarkNinjaString_Value(b *testing.B) {
|
|||
b.Run(strconv.Itoa(l), func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for n := 0; n < b.N; n++ {
|
||||
ns.Value(nil)
|
||||
ns.Value(&nameTracker{})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -377,7 +381,7 @@ func BenchmarkNinjaString_Value(b *testing.B) {
|
|||
b.Run(strconv.Itoa(l), func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for n := 0; n < b.N; n++ {
|
||||
ns.Value(nil)
|
||||
ns.Value(&nameTracker{})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -394,7 +398,7 @@ func BenchmarkNinjaString_Value(b *testing.B) {
|
|||
b.Run(strconv.Itoa(l), func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for n := 0; n < b.N; n++ {
|
||||
ns.Value(nil)
|
||||
ns.Value(&nameTracker{})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ func (n *ninjaWriter) Build(comment string, rule string, outputs, implicitOuts,
|
|||
explicitDeps, implicitDeps, orderOnlyDeps, validations []*ninjaString,
|
||||
outputStrings, implicitOutStrings, explicitDepStrings,
|
||||
implicitDepStrings, orderOnlyDepStrings, validationStrings []string,
|
||||
pkgNames map[*packageContext]string) error {
|
||||
nameTracker *nameTracker) error {
|
||||
|
||||
n.justDidBlankLine = false
|
||||
|
||||
|
@ -144,7 +144,7 @@ func (n *ninjaWriter) Build(comment string, rule string, outputs, implicitOuts,
|
|||
}
|
||||
for _, output := range outputs {
|
||||
wrapper.Space()
|
||||
output.ValueWithEscaper(wrapper, pkgNames, outputEscaper)
|
||||
output.ValueWithEscaper(wrapper, nameTracker, outputEscaper)
|
||||
}
|
||||
|
||||
if len(implicitOuts) > 0 || len(implicitOutStrings) > 0 {
|
||||
|
@ -156,7 +156,7 @@ func (n *ninjaWriter) Build(comment string, rule string, outputs, implicitOuts,
|
|||
}
|
||||
for _, out := range implicitOuts {
|
||||
wrapper.Space()
|
||||
out.ValueWithEscaper(wrapper, pkgNames, outputEscaper)
|
||||
out.ValueWithEscaper(wrapper, nameTracker, outputEscaper)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,7 +170,7 @@ func (n *ninjaWriter) Build(comment string, rule string, outputs, implicitOuts,
|
|||
}
|
||||
for _, dep := range explicitDeps {
|
||||
wrapper.Space()
|
||||
dep.ValueWithEscaper(wrapper, pkgNames, inputEscaper)
|
||||
dep.ValueWithEscaper(wrapper, nameTracker, inputEscaper)
|
||||
}
|
||||
|
||||
if len(implicitDeps) > 0 || len(implicitDepStrings) > 0 {
|
||||
|
@ -182,7 +182,7 @@ func (n *ninjaWriter) Build(comment string, rule string, outputs, implicitOuts,
|
|||
}
|
||||
for _, dep := range implicitDeps {
|
||||
wrapper.Space()
|
||||
dep.ValueWithEscaper(wrapper, pkgNames, inputEscaper)
|
||||
dep.ValueWithEscaper(wrapper, nameTracker, inputEscaper)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,7 +195,7 @@ func (n *ninjaWriter) Build(comment string, rule string, outputs, implicitOuts,
|
|||
}
|
||||
for _, dep := range orderOnlyDeps {
|
||||
wrapper.Space()
|
||||
dep.ValueWithEscaper(wrapper, pkgNames, inputEscaper)
|
||||
dep.ValueWithEscaper(wrapper, nameTracker, inputEscaper)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,7 +208,7 @@ func (n *ninjaWriter) Build(comment string, rule string, outputs, implicitOuts,
|
|||
}
|
||||
for _, dep := range validations {
|
||||
wrapper.Space()
|
||||
dep.ValueWithEscaper(wrapper, pkgNames, inputEscaper)
|
||||
dep.ValueWithEscaper(wrapper, nameTracker, inputEscaper)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -261,7 +261,7 @@ func (n *ninjaWriter) ScopedAssign(name, value string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (n *ninjaWriter) Default(pkgNames map[*packageContext]string, targets []*ninjaString, targetStrings []string) error {
|
||||
func (n *ninjaWriter) Default(nameTracker *nameTracker, targets []*ninjaString, targetStrings []string) error {
|
||||
n.justDidBlankLine = false
|
||||
|
||||
const lineWrapLen = len(" $")
|
||||
|
@ -280,7 +280,7 @@ func (n *ninjaWriter) Default(pkgNames map[*packageContext]string, targets []*ni
|
|||
}
|
||||
for _, target := range targets {
|
||||
wrapper.Space()
|
||||
target.ValueWithEscaper(wrapper, pkgNames, outputEscaper)
|
||||
target.ValueWithEscaper(wrapper, nameTracker, outputEscaper)
|
||||
}
|
||||
|
||||
return wrapper.Flush()
|
||||
|
|
|
@ -250,10 +250,9 @@ func (p *packageContext) ImportAs(as, pkgPath string) {
|
|||
}
|
||||
|
||||
type staticVariable struct {
|
||||
pctx *packageContext
|
||||
name_ string
|
||||
value_ string
|
||||
fullName_ string
|
||||
pctx *packageContext
|
||||
name_ string
|
||||
value_ string
|
||||
}
|
||||
|
||||
// StaticVariable returns a Variable whose value does not depend on any
|
||||
|
@ -294,16 +293,9 @@ func (v *staticVariable) name() string {
|
|||
}
|
||||
|
||||
func (v *staticVariable) fullName(pkgNames map[*packageContext]string) string {
|
||||
if v.fullName_ != "" {
|
||||
return v.fullName_
|
||||
}
|
||||
return packageNamespacePrefix(pkgNames[v.pctx]) + v.name_
|
||||
}
|
||||
|
||||
func (v *staticVariable) memoizeFullName(pkgNames map[*packageContext]string) {
|
||||
v.fullName_ = v.fullName(pkgNames)
|
||||
}
|
||||
|
||||
func (v *staticVariable) value(VariableFuncContext, interface{}) (*ninjaString, error) {
|
||||
ninjaStr, err := parseNinjaString(v.pctx.scope, v.value_)
|
||||
if err != nil {
|
||||
|
@ -318,10 +310,9 @@ func (v *staticVariable) String() string {
|
|||
}
|
||||
|
||||
type variableFunc struct {
|
||||
pctx *packageContext
|
||||
name_ string
|
||||
value_ func(VariableFuncContext, interface{}) (string, error)
|
||||
fullName_ string
|
||||
pctx *packageContext
|
||||
name_ string
|
||||
value_ func(VariableFuncContext, interface{}) (string, error)
|
||||
}
|
||||
|
||||
// VariableFuncContext is passed to VariableFunc functions.
|
||||
|
@ -430,16 +421,9 @@ func (v *variableFunc) name() string {
|
|||
}
|
||||
|
||||
func (v *variableFunc) fullName(pkgNames map[*packageContext]string) string {
|
||||
if v.fullName_ != "" {
|
||||
return v.fullName_
|
||||
}
|
||||
return packageNamespacePrefix(pkgNames[v.pctx]) + v.name_
|
||||
}
|
||||
|
||||
func (v *variableFunc) memoizeFullName(pkgNames map[*packageContext]string) {
|
||||
v.fullName_ = v.fullName(pkgNames)
|
||||
}
|
||||
|
||||
func (v *variableFunc) value(ctx VariableFuncContext, config interface{}) (*ninjaString, error) {
|
||||
value, err := v.value_(ctx, config)
|
||||
if err != nil {
|
||||
|
@ -500,10 +484,6 @@ func (v *argVariable) fullName(pkgNames map[*packageContext]string) string {
|
|||
return v.name_
|
||||
}
|
||||
|
||||
func (v *argVariable) memoizeFullName(pkgNames map[*packageContext]string) {
|
||||
// Nothing to do, full name is known at initialization.
|
||||
}
|
||||
|
||||
func (v *argVariable) value(ctx VariableFuncContext, config interface{}) (*ninjaString, error) {
|
||||
return nil, errVariableIsArg
|
||||
}
|
||||
|
@ -513,10 +493,9 @@ func (v *argVariable) String() string {
|
|||
}
|
||||
|
||||
type staticPool struct {
|
||||
pctx *packageContext
|
||||
name_ string
|
||||
params PoolParams
|
||||
fullName_ string
|
||||
pctx *packageContext
|
||||
name_ string
|
||||
params PoolParams
|
||||
}
|
||||
|
||||
// StaticPool returns a Pool whose value does not depend on any configuration
|
||||
|
@ -558,16 +537,9 @@ func (p *staticPool) name() string {
|
|||
}
|
||||
|
||||
func (p *staticPool) fullName(pkgNames map[*packageContext]string) string {
|
||||
if p.fullName_ != "" {
|
||||
return p.fullName_
|
||||
}
|
||||
return packageNamespacePrefix(pkgNames[p.pctx]) + p.name_
|
||||
}
|
||||
|
||||
func (p *staticPool) memoizeFullName(pkgNames map[*packageContext]string) {
|
||||
p.fullName_ = p.fullName(pkgNames)
|
||||
}
|
||||
|
||||
func (p *staticPool) def(config interface{}) (*poolDef, error) {
|
||||
def, err := parsePoolParams(p.pctx.scope, &p.params)
|
||||
if err != nil {
|
||||
|
@ -584,7 +556,6 @@ type poolFunc struct {
|
|||
pctx *packageContext
|
||||
name_ string
|
||||
paramsFunc func(interface{}) (PoolParams, error)
|
||||
fullName_ string
|
||||
}
|
||||
|
||||
// PoolFunc returns a Pool whose value is determined by a function that takes a
|
||||
|
@ -629,16 +600,9 @@ func (p *poolFunc) name() string {
|
|||
}
|
||||
|
||||
func (p *poolFunc) fullName(pkgNames map[*packageContext]string) string {
|
||||
if p.fullName_ != "" {
|
||||
return p.fullName_
|
||||
}
|
||||
return packageNamespacePrefix(pkgNames[p.pctx]) + p.name_
|
||||
}
|
||||
|
||||
func (p *poolFunc) memoizeFullName(pkgNames map[*packageContext]string) {
|
||||
p.fullName_ = p.fullName(pkgNames)
|
||||
}
|
||||
|
||||
func (p *poolFunc) def(config interface{}) (*poolDef, error) {
|
||||
params, err := p.paramsFunc(config)
|
||||
if err != nil {
|
||||
|
@ -671,10 +635,6 @@ func (p *builtinPool) fullName(pkgNames map[*packageContext]string) string {
|
|||
return p.name_
|
||||
}
|
||||
|
||||
func (p *builtinPool) memoizeFullName(pkgNames map[*packageContext]string) {
|
||||
// Nothing to do, full name is known at initialization.
|
||||
}
|
||||
|
||||
func (p *builtinPool) def(config interface{}) (*poolDef, error) {
|
||||
return nil, errPoolIsBuiltin
|
||||
}
|
||||
|
@ -696,7 +656,6 @@ type staticRule struct {
|
|||
params RuleParams
|
||||
argNames map[string]bool
|
||||
scope_ *basicScope
|
||||
fullName_ string
|
||||
sync.Mutex // protects scope_ during lazy creation
|
||||
}
|
||||
|
||||
|
@ -764,16 +723,9 @@ func (r *staticRule) name() string {
|
|||
}
|
||||
|
||||
func (r *staticRule) fullName(pkgNames map[*packageContext]string) string {
|
||||
if r.fullName_ != "" {
|
||||
return r.fullName_
|
||||
}
|
||||
return packageNamespacePrefix(pkgNames[r.pctx]) + r.name_
|
||||
}
|
||||
|
||||
func (r *staticRule) memoizeFullName(pkgNames map[*packageContext]string) {
|
||||
r.fullName_ = r.fullName(pkgNames)
|
||||
}
|
||||
|
||||
func (r *staticRule) def(interface{}) (*ruleDef, error) {
|
||||
def, err := parseRuleParams(r.scope(), &r.params)
|
||||
if err != nil {
|
||||
|
@ -809,7 +761,6 @@ type ruleFunc struct {
|
|||
paramsFunc func(interface{}) (RuleParams, error)
|
||||
argNames map[string]bool
|
||||
scope_ *basicScope
|
||||
fullName_ string
|
||||
sync.Mutex // protects scope_ during lazy creation
|
||||
}
|
||||
|
||||
|
@ -878,16 +829,9 @@ func (r *ruleFunc) name() string {
|
|||
}
|
||||
|
||||
func (r *ruleFunc) fullName(pkgNames map[*packageContext]string) string {
|
||||
if r.fullName_ != "" {
|
||||
return r.fullName_
|
||||
}
|
||||
return packageNamespacePrefix(pkgNames[r.pctx]) + r.name_
|
||||
}
|
||||
|
||||
func (r *ruleFunc) memoizeFullName(pkgNames map[*packageContext]string) {
|
||||
r.fullName_ = r.fullName(pkgNames)
|
||||
}
|
||||
|
||||
func (r *ruleFunc) def(config interface{}) (*ruleDef, error) {
|
||||
params, err := r.paramsFunc(config)
|
||||
if err != nil {
|
||||
|
@ -939,10 +883,6 @@ func (r *builtinRule) fullName(pkgNames map[*packageContext]string) string {
|
|||
return r.name_
|
||||
}
|
||||
|
||||
func (r *builtinRule) memoizeFullName(pkgNames map[*packageContext]string) {
|
||||
// Nothing to do, full name is known at initialization.
|
||||
}
|
||||
|
||||
func (r *builtinRule) def(config interface{}) (*ruleDef, error) {
|
||||
return nil, errRuleIsBuiltin
|
||||
}
|
||||
|
|
49
scope.go
49
scope.go
|
@ -28,7 +28,6 @@ type Variable interface {
|
|||
packageContext() *packageContext
|
||||
name() string // "foo"
|
||||
fullName(pkgNames map[*packageContext]string) string // "pkg.foo" or "path.to.pkg.foo"
|
||||
memoizeFullName(pkgNames map[*packageContext]string) // precompute fullName if desired
|
||||
value(ctx VariableFuncContext, config interface{}) (*ninjaString, error)
|
||||
String() string
|
||||
}
|
||||
|
@ -39,7 +38,6 @@ type Pool interface {
|
|||
packageContext() *packageContext
|
||||
name() string // "foo"
|
||||
fullName(pkgNames map[*packageContext]string) string // "pkg.foo" or "path.to.pkg.foo"
|
||||
memoizeFullName(pkgNames map[*packageContext]string) // precompute fullName if desired
|
||||
def(config interface{}) (*poolDef, error)
|
||||
String() string
|
||||
}
|
||||
|
@ -50,7 +48,6 @@ type Rule interface {
|
|||
packageContext() *packageContext
|
||||
name() string // "foo"
|
||||
fullName(pkgNames map[*packageContext]string) string // "pkg.foo" or "path.to.pkg.foo"
|
||||
memoizeFullName(pkgNames map[*packageContext]string) // precompute fullName if desired
|
||||
def(config interface{}) (*ruleDef, error)
|
||||
scope() *basicScope
|
||||
isArg(argName string) bool
|
||||
|
@ -369,10 +366,6 @@ func (l *localVariable) fullName(pkgNames map[*packageContext]string) string {
|
|||
return l.fullName_
|
||||
}
|
||||
|
||||
func (l *localVariable) memoizeFullName(pkgNames map[*packageContext]string) {
|
||||
// Nothing to do, full name is known at initialization.
|
||||
}
|
||||
|
||||
func (l *localVariable) value(VariableFuncContext, interface{}) (*ninjaString, error) {
|
||||
return l.value_, nil
|
||||
}
|
||||
|
@ -401,10 +394,6 @@ func (l *localRule) fullName(pkgNames map[*packageContext]string) string {
|
|||
return l.fullName_
|
||||
}
|
||||
|
||||
func (l *localRule) memoizeFullName(pkgNames map[*packageContext]string) {
|
||||
// Nothing to do, full name is known at initialization.
|
||||
}
|
||||
|
||||
func (l *localRule) def(interface{}) (*ruleDef, error) {
|
||||
return l.def_, nil
|
||||
}
|
||||
|
@ -420,3 +409,41 @@ func (r *localRule) isArg(argName string) bool {
|
|||
func (r *localRule) String() string {
|
||||
return "<local rule>:" + r.fullName_
|
||||
}
|
||||
|
||||
type nameTracker struct {
|
||||
variables map[Variable]string
|
||||
rules map[Rule]string
|
||||
pools map[Pool]string
|
||||
|
||||
pkgNames map[*packageContext]string
|
||||
}
|
||||
|
||||
func (m *nameTracker) Variable(v Variable) string {
|
||||
if m == nil {
|
||||
return v.fullName(nil)
|
||||
}
|
||||
if name, ok := m.variables[v]; ok {
|
||||
return name
|
||||
}
|
||||
return v.fullName(m.pkgNames)
|
||||
}
|
||||
|
||||
func (m *nameTracker) Rule(r Rule) string {
|
||||
if m == nil {
|
||||
return r.fullName(nil)
|
||||
}
|
||||
if name, ok := m.rules[r]; ok {
|
||||
return name
|
||||
}
|
||||
return r.fullName(m.pkgNames)
|
||||
}
|
||||
|
||||
func (m *nameTracker) Pool(p Pool) string {
|
||||
if m == nil {
|
||||
return p.fullName(nil)
|
||||
}
|
||||
if name, ok := m.pools[p]; ok {
|
||||
return name
|
||||
}
|
||||
return p.fullName(m.pkgNames)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue