Move name memoization out of variables
memoizeFullName was added to variables, rules and pools as an optimization to prevent recomputing the full name repeatedly, but the storage of variables, rules and pools are generally global and not tied to the Context. When running multiple tests in parallel there will be multiple Context objects all trying to update the memoized names on the global variables, causing a data race. Package names were previously memoized via a pkgNames map stored on the Context. Expand pkgNames to a nameTracker object that contains maps for packages, variables, rules and pools, and replace calls to fullName with calls through nameTracker. Test: context_test.go Change-Id: I15040b85a6d1dab9ab3cff44f227b22985acee18
This commit is contained in:
parent
2f0f395cc9
commit
6bc984abca
7 changed files with 141 additions and 185 deletions
128
context.go
128
context.go
|
@ -16,6 +16,7 @@ package blueprint
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"cmp"
|
||||||
"context"
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
@ -29,6 +30,7 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"runtime/pprof"
|
"runtime/pprof"
|
||||||
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -100,7 +102,7 @@ type Context struct {
|
||||||
allowMissingDependencies bool
|
allowMissingDependencies bool
|
||||||
|
|
||||||
// set during PrepareBuildActions
|
// set during PrepareBuildActions
|
||||||
pkgNames map[*packageContext]string
|
nameTracker *nameTracker
|
||||||
liveGlobals *liveTracker
|
liveGlobals *liveTracker
|
||||||
globalVariables map[Variable]*ninjaString
|
globalVariables map[Variable]*ninjaString
|
||||||
globalPools map[Pool]*poolDef
|
globalPools map[Pool]*poolDef
|
||||||
|
@ -2741,7 +2743,7 @@ func jsonModuleFromModuleInfo(m *moduleInfo) *JsonModule {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func jsonModuleWithActionsFromModuleInfo(m *moduleInfo) *JsonModule {
|
func jsonModuleWithActionsFromModuleInfo(m *moduleInfo, nameTracker *nameTracker) *JsonModule {
|
||||||
result := &JsonModule{
|
result := &JsonModule{
|
||||||
jsonModuleName: jsonModuleName{
|
jsonModuleName: jsonModuleName{
|
||||||
Name: m.Name(),
|
Name: m.Name(),
|
||||||
|
@ -2758,17 +2760,17 @@ func jsonModuleWithActionsFromModuleInfo(m *moduleInfo) *JsonModule {
|
||||||
Inputs: append(append(append(
|
Inputs: append(append(append(
|
||||||
bDef.InputStrings,
|
bDef.InputStrings,
|
||||||
bDef.ImplicitStrings...),
|
bDef.ImplicitStrings...),
|
||||||
getNinjaStringsWithNilPkgNames(bDef.Inputs)...),
|
getNinjaStrings(bDef.Inputs, nameTracker)...),
|
||||||
getNinjaStringsWithNilPkgNames(bDef.Implicits)...),
|
getNinjaStrings(bDef.Implicits, nameTracker)...),
|
||||||
|
|
||||||
Outputs: append(append(append(
|
Outputs: append(append(append(
|
||||||
bDef.OutputStrings,
|
bDef.OutputStrings,
|
||||||
bDef.ImplicitOutputStrings...),
|
bDef.ImplicitOutputStrings...),
|
||||||
getNinjaStringsWithNilPkgNames(bDef.Outputs)...),
|
getNinjaStrings(bDef.Outputs, nameTracker)...),
|
||||||
getNinjaStringsWithNilPkgNames(bDef.ImplicitOutputs)...),
|
getNinjaStrings(bDef.ImplicitOutputs, nameTracker)...),
|
||||||
}
|
}
|
||||||
if d, ok := bDef.Variables["description"]; ok {
|
if d, ok := bDef.Variables["description"]; ok {
|
||||||
a.Desc = d.Value(nil)
|
a.Desc = d.Value(nameTracker)
|
||||||
}
|
}
|
||||||
actions = append(actions, a)
|
actions = append(actions, a)
|
||||||
}
|
}
|
||||||
|
@ -2786,12 +2788,11 @@ func jsonModuleWithActionsFromModuleInfo(m *moduleInfo) *JsonModule {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets a list of strings from the given list of ninjaStrings by invoking ninjaString.Value with
|
// Gets a list of strings from the given list of ninjaStrings by invoking ninjaString.Value on each.
|
||||||
// nil pkgNames on each of the input ninjaStrings.
|
func getNinjaStrings(nStrs []*ninjaString, nameTracker *nameTracker) []string {
|
||||||
func getNinjaStringsWithNilPkgNames(nStrs []*ninjaString) []string {
|
|
||||||
var strs []string
|
var strs []string
|
||||||
for _, nstr := range nStrs {
|
for _, nstr := range nStrs {
|
||||||
strs = append(strs, nstr.Value(nil))
|
strs = append(strs, nstr.Value(nameTracker))
|
||||||
}
|
}
|
||||||
return strs
|
return strs
|
||||||
}
|
}
|
||||||
|
@ -2799,7 +2800,7 @@ func getNinjaStringsWithNilPkgNames(nStrs []*ninjaString) []string {
|
||||||
func (c *Context) GetWeightedOutputsFromPredicate(predicate func(*JsonModule) (bool, int)) map[string]int {
|
func (c *Context) GetWeightedOutputsFromPredicate(predicate func(*JsonModule) (bool, int)) map[string]int {
|
||||||
outputToWeight := make(map[string]int)
|
outputToWeight := make(map[string]int)
|
||||||
for _, m := range c.modulesSorted {
|
for _, m := range c.modulesSorted {
|
||||||
jmWithActions := jsonModuleWithActionsFromModuleInfo(m)
|
jmWithActions := jsonModuleWithActionsFromModuleInfo(m, c.nameTracker)
|
||||||
if ok, weight := predicate(jmWithActions); ok {
|
if ok, weight := predicate(jmWithActions); ok {
|
||||||
for _, a := range jmWithActions.Module["Actions"].([]JSONAction) {
|
for _, a := range jmWithActions.Module["Actions"].([]JSONAction) {
|
||||||
for _, o := range a.Outputs {
|
for _, o := range a.Outputs {
|
||||||
|
@ -2831,7 +2832,7 @@ func (c *Context) PrintJSONGraphAndActions(wGraph io.Writer, wActions io.Writer)
|
||||||
modulesToActions := make([]*JsonModule, 0)
|
modulesToActions := make([]*JsonModule, 0)
|
||||||
for _, m := range c.modulesSorted {
|
for _, m := range c.modulesSorted {
|
||||||
jm := jsonModuleFromModuleInfo(m)
|
jm := jsonModuleFromModuleInfo(m)
|
||||||
jmWithActions := jsonModuleWithActionsFromModuleInfo(m)
|
jmWithActions := jsonModuleWithActionsFromModuleInfo(m, c.nameTracker)
|
||||||
for _, d := range m.directDeps {
|
for _, d := range m.directDeps {
|
||||||
jm.Deps = append(jm.Deps, jsonDep{
|
jm.Deps = append(jm.Deps, jsonDep{
|
||||||
jsonModuleName: *jsonModuleNameFromModuleInfo(d.module),
|
jsonModuleName: *jsonModuleNameFromModuleInfo(d.module),
|
||||||
|
@ -2918,12 +2919,12 @@ func (c *Context) PrepareBuildActions(config interface{}) (deps []string, errs [
|
||||||
|
|
||||||
deps = append(deps, depsPackages...)
|
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.
|
// 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.globalVariables = c.liveGlobals.variables
|
||||||
c.globalPools = c.liveGlobals.pools
|
c.globalPools = c.liveGlobals.pools
|
||||||
c.globalRules = c.liveGlobals.rules
|
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
|
// 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
|
// guaranteed to be used at least twice, once in the definition and once for each usage, and many
|
||||||
// are used much more than once.
|
// 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 {
|
for v := range liveGlobals.variables {
|
||||||
v.memoizeFullName(pkgNames)
|
nameTracker.variables[v] = v.fullName(pkgNames)
|
||||||
}
|
}
|
||||||
for r := range liveGlobals.rules {
|
for r := range liveGlobals.rules {
|
||||||
r.memoizeFullName(pkgNames)
|
nameTracker.rules[r] = r.fullName(pkgNames)
|
||||||
}
|
}
|
||||||
for p := range liveGlobals.pools {
|
for p := range liveGlobals.pools {
|
||||||
p.memoizeFullName(pkgNames)
|
nameTracker.pools[p] = p.fullName(pkgNames)
|
||||||
}
|
}
|
||||||
|
return nameTracker
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) checkForVariableReferenceCycles(
|
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
|
visited := make(map[Variable]bool) // variables that were already checked
|
||||||
checking := make(map[Variable]bool) // variables actively being checked
|
checking := make(map[Variable]bool) // variables actively being checked
|
||||||
|
@ -3905,12 +3913,12 @@ func (c *Context) checkForVariableReferenceCycles(
|
||||||
msgs := []string{"detected variable reference cycle:"}
|
msgs := []string{"detected variable reference cycle:"}
|
||||||
|
|
||||||
// Iterate backwards through the cycle list.
|
// Iterate backwards through the cycle list.
|
||||||
curName := v.fullName(pkgNames)
|
curName := nameTracker.Variable(v)
|
||||||
curValue := value.Value(pkgNames)
|
curValue := value.Value(nameTracker)
|
||||||
for i := len(cycle) - 1; i >= 0; i-- {
|
for i := len(cycle) - 1; i >= 0; i-- {
|
||||||
next := cycle[i]
|
next := cycle[i]
|
||||||
nextName := next.fullName(pkgNames)
|
nextName := nameTracker.Variable(next)
|
||||||
nextValue := variables[next].Value(pkgNames)
|
nextValue := variables[next].Value(nameTracker)
|
||||||
|
|
||||||
msgs = append(msgs, fmt.Sprintf(
|
msgs = append(msgs, fmt.Sprintf(
|
||||||
" %q depends on %q", curName, nextName))
|
" %q depends on %q", curName, nextName))
|
||||||
|
@ -3958,7 +3966,7 @@ func (c *Context) AllTargets() (map[string]string, error) {
|
||||||
targets := map[string]string{}
|
targets := map[string]string{}
|
||||||
var collectTargets = func(actionDefs localBuildActions) error {
|
var collectTargets = func(actionDefs localBuildActions) error {
|
||||||
for _, buildDef := range actionDefs.buildDefs {
|
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...) {
|
for _, output := range append(buildDef.Outputs, buildDef.ImplicitOutputs...) {
|
||||||
outputValue, err := output.Eval(c.globalVariables)
|
outputValue, err := output.Eval(c.globalVariables)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -4266,7 +4274,7 @@ func (c *Context) writeBuildFileHeader(nw *ninjaWriter) error {
|
||||||
|
|
||||||
var pkgs []pkgAssociation
|
var pkgs []pkgAssociation
|
||||||
maxNameLen := 0
|
maxNameLen := 0
|
||||||
for pkg, name := range c.pkgNames {
|
for pkg, name := range c.nameTracker.pkgNames {
|
||||||
pkgs = append(pkgs, pkgAssociation{
|
pkgs = append(pkgs, pkgAssociation{
|
||||||
PkgName: name,
|
PkgName: name,
|
||||||
PkgPath: pkg.pkgPath,
|
PkgPath: pkg.pkgPath,
|
||||||
|
@ -4319,7 +4327,7 @@ func (c *Context) writeSubninjas(nw *ninjaWriter) error {
|
||||||
|
|
||||||
func (c *Context) writeBuildDir(nw *ninjaWriter) error {
|
func (c *Context) writeBuildDir(nw *ninjaWriter) error {
|
||||||
if c.outDir != nil {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -4332,29 +4340,6 @@ func (c *Context) writeBuildDir(nw *ninjaWriter) error {
|
||||||
return nil
|
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 {
|
func (c *Context) writeGlobalVariables(nw *ninjaWriter) error {
|
||||||
visited := make(map[Variable]bool)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -4386,15 +4371,16 @@ func (c *Context) writeGlobalVariables(nw *ninjaWriter) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
globalVariables := make([]globalEntity, 0, len(c.globalVariables))
|
globalVariables := make([]Variable, 0, len(c.globalVariables))
|
||||||
for variable := range c.globalVariables {
|
for variable := range c.globalVariables {
|
||||||
globalVariables = append(globalVariables, variable)
|
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 {
|
for _, v := range globalVariables {
|
||||||
v := entity.(Variable)
|
|
||||||
if !visited[v] {
|
if !visited[v] {
|
||||||
err := walk(v)
|
err := walk(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -4407,16 +4393,17 @@ func (c *Context) writeGlobalVariables(nw *ninjaWriter) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) writeGlobalPools(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 {
|
for pool := range c.globalPools {
|
||||||
globalPools = append(globalPools, pool)
|
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 {
|
for _, pool := range globalPools {
|
||||||
pool := entity.(Pool)
|
name := c.nameTracker.Pool(pool)
|
||||||
name := pool.fullName(c.pkgNames)
|
|
||||||
def := c.globalPools[pool]
|
def := c.globalPools[pool]
|
||||||
err := def.WriteTo(nw, name)
|
err := def.WriteTo(nw, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -4433,18 +4420,19 @@ func (c *Context) writeGlobalPools(nw *ninjaWriter) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) writeGlobalRules(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 {
|
for rule := range c.globalRules {
|
||||||
globalRules = append(globalRules, rule)
|
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 {
|
for _, rule := range globalRules {
|
||||||
rule := entity.(Rule)
|
name := c.nameTracker.Rule(rule)
|
||||||
name := rule.fullName(c.pkgNames)
|
|
||||||
def := c.globalRules[rule]
|
def := c.globalRules[rule]
|
||||||
err := def.WriteTo(nw, name, c.pkgNames)
|
err := def.WriteTo(nw, name, c.nameTracker)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -4766,7 +4754,7 @@ func (c *Context) writeLocalBuildActions(nw *ninjaWriter,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
err = nw.Assign(name, value.Value(c.pkgNames))
|
err = nw.Assign(name, value.Value(c.nameTracker))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -4789,7 +4777,7 @@ func (c *Context) writeLocalBuildActions(nw *ninjaWriter,
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = def.WriteTo(nw, name, c.pkgNames)
|
err = def.WriteTo(nw, name, c.nameTracker)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -4802,7 +4790,7 @@ func (c *Context) writeLocalBuildActions(nw *ninjaWriter,
|
||||||
|
|
||||||
// Write the build definitions.
|
// Write the build definitions.
|
||||||
for _, buildDef := range defs.buildDefs {
|
for _, buildDef := range defs.buildDefs {
|
||||||
err := buildDef.WriteTo(nw, c.pkgNames)
|
err := buildDef.WriteTo(nw, c.nameTracker)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,8 +229,7 @@ func parseRuleParams(scope scope, params *RuleParams) (*ruleDef,
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ruleDef) WriteTo(nw *ninjaWriter, name string,
|
func (r *ruleDef) WriteTo(nw *ninjaWriter, name string, nameTracker *nameTracker) error {
|
||||||
pkgNames map[*packageContext]string) error {
|
|
||||||
|
|
||||||
if r.Comment != "" {
|
if r.Comment != "" {
|
||||||
err := nw.Comment(r.Comment)
|
err := nw.Comment(r.Comment)
|
||||||
|
@ -245,13 +244,13 @@ func (r *ruleDef) WriteTo(nw *ninjaWriter, name string,
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.Pool != nil {
|
if r.Pool != nil {
|
||||||
err = nw.ScopedAssign("pool", r.Pool.fullName(pkgNames))
|
err = nw.ScopedAssign("pool", nameTracker.Pool(r.Pool))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = writeVariables(nw, r.Variables, pkgNames)
|
err = writeVariables(nw, r.Variables, nameTracker)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -415,10 +414,10 @@ func parseBuildParams(scope scope, params *BuildParams,
|
||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *buildDef) WriteTo(nw *ninjaWriter, pkgNames map[*packageContext]string) error {
|
func (b *buildDef) WriteTo(nw *ninjaWriter, nameTracker *nameTracker) error {
|
||||||
var (
|
var (
|
||||||
comment = b.Comment
|
comment = b.Comment
|
||||||
rule = b.Rule.fullName(pkgNames)
|
rule = nameTracker.Rule(b.Rule)
|
||||||
outputs = b.Outputs
|
outputs = b.Outputs
|
||||||
implicitOuts = b.ImplicitOutputs
|
implicitOuts = b.ImplicitOutputs
|
||||||
explicitDeps = b.Inputs
|
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,
|
err := nw.Build(comment, rule, outputs, implicitOuts, explicitDeps, implicitDeps, orderOnlyDeps, validations,
|
||||||
outputStrings, implicitOutStrings, explicitDepStrings,
|
outputStrings, implicitOutStrings, explicitDepStrings,
|
||||||
implicitDepStrings, orderOnlyDepStrings, validationStrings,
|
implicitDepStrings, orderOnlyDepStrings, validationStrings,
|
||||||
pkgNames)
|
nameTracker)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = writeVariables(nw, b.Variables, pkgNames)
|
err = writeVariables(nw, b.Variables, nameTracker)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -458,8 +457,8 @@ func (b *buildDef) WriteTo(nw *ninjaWriter, pkgNames map[*packageContext]string)
|
||||||
args := make([]nameValuePair, 0, len(b.Args))
|
args := make([]nameValuePair, 0, len(b.Args))
|
||||||
|
|
||||||
for argVar, value := range b.Args {
|
for argVar, value := range b.Args {
|
||||||
fullName := argVar.fullName(pkgNames)
|
fullName := nameTracker.Variable(argVar)
|
||||||
args = append(args, nameValuePair{fullName, value.Value(pkgNames)})
|
args = append(args, nameValuePair{fullName, value.Value(nameTracker)})
|
||||||
}
|
}
|
||||||
sort.Slice(args, func(i, j int) bool { return args[i].name < args[j].name })
|
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 {
|
if !b.Optional {
|
||||||
err = nw.Default(pkgNames, outputs, outputStrings)
|
err = nw.Default(nameTracker, outputs, outputStrings)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -480,8 +479,7 @@ func (b *buildDef) WriteTo(nw *ninjaWriter, pkgNames map[*packageContext]string)
|
||||||
return nw.BlankLine()
|
return nw.BlankLine()
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeVariables(nw *ninjaWriter, variables map[string]*ninjaString,
|
func writeVariables(nw *ninjaWriter, variables map[string]*ninjaString, nameTracker *nameTracker) error {
|
||||||
pkgNames map[*packageContext]string) error {
|
|
||||||
var keys []string
|
var keys []string
|
||||||
for k := range variables {
|
for k := range variables {
|
||||||
keys = append(keys, k)
|
keys = append(keys, k)
|
||||||
|
@ -489,7 +487,7 @@ func writeVariables(nw *ninjaWriter, variables map[string]*ninjaString,
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
|
|
||||||
for _, name := range keys {
|
for _, name := range keys {
|
||||||
err := nw.ScopedAssign(name, variables[name].Value(pkgNames))
|
err := nw.ScopedAssign(name, variables[name].Value(nameTracker))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -324,17 +324,16 @@ func parseNinjaOrSimpleStrings(scope scope, strs []string) ([]*ninjaString, []st
|
||||||
return ninjaStrings, simpleStrings, nil
|
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 {
|
if n.variables == nil || len(*n.variables) == 0 {
|
||||||
return defaultEscaper.Replace(n.str)
|
return defaultEscaper.Replace(n.str)
|
||||||
}
|
}
|
||||||
str := &strings.Builder{}
|
str := &strings.Builder{}
|
||||||
n.ValueWithEscaper(str, pkgNames, defaultEscaper)
|
n.ValueWithEscaper(str, nameTracker, defaultEscaper)
|
||||||
return str.String()
|
return str.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *ninjaString) ValueWithEscaper(w io.StringWriter, pkgNames map[*packageContext]string,
|
func (n *ninjaString) ValueWithEscaper(w io.StringWriter, nameTracker *nameTracker, escaper *strings.Replacer) {
|
||||||
escaper *strings.Replacer) {
|
|
||||||
|
|
||||||
if n.variables == nil || len(*n.variables) == 0 {
|
if n.variables == nil || len(*n.variables) == 0 {
|
||||||
w.WriteString(escaper.Replace(n.str))
|
w.WriteString(escaper.Replace(n.str))
|
||||||
|
@ -348,7 +347,7 @@ func (n *ninjaString) ValueWithEscaper(w io.StringWriter, pkgNames map[*packageC
|
||||||
w.WriteString("$ ")
|
w.WriteString("$ ")
|
||||||
} else {
|
} else {
|
||||||
w.WriteString("${")
|
w.WriteString("${")
|
||||||
w.WriteString(v.variable.fullName(pkgNames))
|
w.WriteString(nameTracker.Variable(v.variable))
|
||||||
w.WriteString("}")
|
w.WriteString("}")
|
||||||
}
|
}
|
||||||
i = int(v.end)
|
i = int(v.end)
|
||||||
|
|
|
@ -164,7 +164,7 @@ func TestParseNinjaString(t *testing.T) {
|
||||||
|
|
||||||
output, err := parseNinjaString(scope, testCase.input)
|
output, err := parseNinjaString(scope, testCase.input)
|
||||||
if err == nil {
|
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)
|
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) {
|
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 := newScope(nil)
|
||||||
impScope.AddVariable(ImpVar)
|
impScope.AddVariable(ImpVar)
|
||||||
scope := newScope(nil)
|
scope := newScope(nil)
|
||||||
|
@ -211,7 +215,7 @@ func TestParseNinjaStringWithImportedVar(t *testing.T) {
|
||||||
t.Errorf(" got: %#v", *output.variables)
|
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)
|
t.Errorf("incorrect Value output, want %q got %q", w, g)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -289,7 +293,7 @@ func Test_parseNinjaOrSimpleStrings(t *testing.T) {
|
||||||
if gotNinjaStrings != nil {
|
if gotNinjaStrings != nil {
|
||||||
evaluatedNinjaStrings = make([]string, 0, len(gotNinjaStrings))
|
evaluatedNinjaStrings = make([]string, 0, len(gotNinjaStrings))
|
||||||
for _, ns := range 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.Run(strconv.Itoa(l), func(b *testing.B) {
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
for n := 0; n < b.N; n++ {
|
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.Run(strconv.Itoa(l), func(b *testing.B) {
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
for n := 0; n < b.N; n++ {
|
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.Run(strconv.Itoa(l), func(b *testing.B) {
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
for n := 0; n < b.N; n++ {
|
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,
|
explicitDeps, implicitDeps, orderOnlyDeps, validations []*ninjaString,
|
||||||
outputStrings, implicitOutStrings, explicitDepStrings,
|
outputStrings, implicitOutStrings, explicitDepStrings,
|
||||||
implicitDepStrings, orderOnlyDepStrings, validationStrings []string,
|
implicitDepStrings, orderOnlyDepStrings, validationStrings []string,
|
||||||
pkgNames map[*packageContext]string) error {
|
nameTracker *nameTracker) error {
|
||||||
|
|
||||||
n.justDidBlankLine = false
|
n.justDidBlankLine = false
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ func (n *ninjaWriter) Build(comment string, rule string, outputs, implicitOuts,
|
||||||
}
|
}
|
||||||
for _, output := range outputs {
|
for _, output := range outputs {
|
||||||
wrapper.Space()
|
wrapper.Space()
|
||||||
output.ValueWithEscaper(wrapper, pkgNames, outputEscaper)
|
output.ValueWithEscaper(wrapper, nameTracker, outputEscaper)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(implicitOuts) > 0 || len(implicitOutStrings) > 0 {
|
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 {
|
for _, out := range implicitOuts {
|
||||||
wrapper.Space()
|
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 {
|
for _, dep := range explicitDeps {
|
||||||
wrapper.Space()
|
wrapper.Space()
|
||||||
dep.ValueWithEscaper(wrapper, pkgNames, inputEscaper)
|
dep.ValueWithEscaper(wrapper, nameTracker, inputEscaper)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(implicitDeps) > 0 || len(implicitDepStrings) > 0 {
|
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 {
|
for _, dep := range implicitDeps {
|
||||||
wrapper.Space()
|
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 {
|
for _, dep := range orderOnlyDeps {
|
||||||
wrapper.Space()
|
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 {
|
for _, dep := range validations {
|
||||||
wrapper.Space()
|
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
|
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
|
n.justDidBlankLine = false
|
||||||
|
|
||||||
const lineWrapLen = len(" $")
|
const lineWrapLen = len(" $")
|
||||||
|
@ -280,7 +280,7 @@ func (n *ninjaWriter) Default(pkgNames map[*packageContext]string, targets []*ni
|
||||||
}
|
}
|
||||||
for _, target := range targets {
|
for _, target := range targets {
|
||||||
wrapper.Space()
|
wrapper.Space()
|
||||||
target.ValueWithEscaper(wrapper, pkgNames, outputEscaper)
|
target.ValueWithEscaper(wrapper, nameTracker, outputEscaper)
|
||||||
}
|
}
|
||||||
|
|
||||||
return wrapper.Flush()
|
return wrapper.Flush()
|
||||||
|
|
|
@ -250,10 +250,9 @@ func (p *packageContext) ImportAs(as, pkgPath string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type staticVariable struct {
|
type staticVariable struct {
|
||||||
pctx *packageContext
|
pctx *packageContext
|
||||||
name_ string
|
name_ string
|
||||||
value_ string
|
value_ string
|
||||||
fullName_ string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// StaticVariable returns a Variable whose value does not depend on any
|
// 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 {
|
func (v *staticVariable) fullName(pkgNames map[*packageContext]string) string {
|
||||||
if v.fullName_ != "" {
|
|
||||||
return v.fullName_
|
|
||||||
}
|
|
||||||
return packageNamespacePrefix(pkgNames[v.pctx]) + v.name_
|
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) {
|
func (v *staticVariable) value(VariableFuncContext, interface{}) (*ninjaString, error) {
|
||||||
ninjaStr, err := parseNinjaString(v.pctx.scope, v.value_)
|
ninjaStr, err := parseNinjaString(v.pctx.scope, v.value_)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -318,10 +310,9 @@ func (v *staticVariable) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
type variableFunc struct {
|
type variableFunc struct {
|
||||||
pctx *packageContext
|
pctx *packageContext
|
||||||
name_ string
|
name_ string
|
||||||
value_ func(VariableFuncContext, interface{}) (string, error)
|
value_ func(VariableFuncContext, interface{}) (string, error)
|
||||||
fullName_ string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// VariableFuncContext is passed to VariableFunc functions.
|
// VariableFuncContext is passed to VariableFunc functions.
|
||||||
|
@ -430,16 +421,9 @@ func (v *variableFunc) name() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *variableFunc) fullName(pkgNames map[*packageContext]string) string {
|
func (v *variableFunc) fullName(pkgNames map[*packageContext]string) string {
|
||||||
if v.fullName_ != "" {
|
|
||||||
return v.fullName_
|
|
||||||
}
|
|
||||||
return packageNamespacePrefix(pkgNames[v.pctx]) + v.name_
|
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) {
|
func (v *variableFunc) value(ctx VariableFuncContext, config interface{}) (*ninjaString, error) {
|
||||||
value, err := v.value_(ctx, config)
|
value, err := v.value_(ctx, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -500,10 +484,6 @@ func (v *argVariable) fullName(pkgNames map[*packageContext]string) string {
|
||||||
return v.name_
|
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) {
|
func (v *argVariable) value(ctx VariableFuncContext, config interface{}) (*ninjaString, error) {
|
||||||
return nil, errVariableIsArg
|
return nil, errVariableIsArg
|
||||||
}
|
}
|
||||||
|
@ -513,10 +493,9 @@ func (v *argVariable) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
type staticPool struct {
|
type staticPool struct {
|
||||||
pctx *packageContext
|
pctx *packageContext
|
||||||
name_ string
|
name_ string
|
||||||
params PoolParams
|
params PoolParams
|
||||||
fullName_ string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// StaticPool returns a Pool whose value does not depend on any configuration
|
// 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 {
|
func (p *staticPool) fullName(pkgNames map[*packageContext]string) string {
|
||||||
if p.fullName_ != "" {
|
|
||||||
return p.fullName_
|
|
||||||
}
|
|
||||||
return packageNamespacePrefix(pkgNames[p.pctx]) + p.name_
|
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) {
|
func (p *staticPool) def(config interface{}) (*poolDef, error) {
|
||||||
def, err := parsePoolParams(p.pctx.scope, &p.params)
|
def, err := parsePoolParams(p.pctx.scope, &p.params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -584,7 +556,6 @@ type poolFunc struct {
|
||||||
pctx *packageContext
|
pctx *packageContext
|
||||||
name_ string
|
name_ string
|
||||||
paramsFunc func(interface{}) (PoolParams, error)
|
paramsFunc func(interface{}) (PoolParams, error)
|
||||||
fullName_ string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PoolFunc returns a Pool whose value is determined by a function that takes a
|
// 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 {
|
func (p *poolFunc) fullName(pkgNames map[*packageContext]string) string {
|
||||||
if p.fullName_ != "" {
|
|
||||||
return p.fullName_
|
|
||||||
}
|
|
||||||
return packageNamespacePrefix(pkgNames[p.pctx]) + p.name_
|
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) {
|
func (p *poolFunc) def(config interface{}) (*poolDef, error) {
|
||||||
params, err := p.paramsFunc(config)
|
params, err := p.paramsFunc(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -671,10 +635,6 @@ func (p *builtinPool) fullName(pkgNames map[*packageContext]string) string {
|
||||||
return p.name_
|
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) {
|
func (p *builtinPool) def(config interface{}) (*poolDef, error) {
|
||||||
return nil, errPoolIsBuiltin
|
return nil, errPoolIsBuiltin
|
||||||
}
|
}
|
||||||
|
@ -696,7 +656,6 @@ type staticRule struct {
|
||||||
params RuleParams
|
params RuleParams
|
||||||
argNames map[string]bool
|
argNames map[string]bool
|
||||||
scope_ *basicScope
|
scope_ *basicScope
|
||||||
fullName_ string
|
|
||||||
sync.Mutex // protects scope_ during lazy creation
|
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 {
|
func (r *staticRule) fullName(pkgNames map[*packageContext]string) string {
|
||||||
if r.fullName_ != "" {
|
|
||||||
return r.fullName_
|
|
||||||
}
|
|
||||||
return packageNamespacePrefix(pkgNames[r.pctx]) + r.name_
|
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) {
|
func (r *staticRule) def(interface{}) (*ruleDef, error) {
|
||||||
def, err := parseRuleParams(r.scope(), &r.params)
|
def, err := parseRuleParams(r.scope(), &r.params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -809,7 +761,6 @@ type ruleFunc struct {
|
||||||
paramsFunc func(interface{}) (RuleParams, error)
|
paramsFunc func(interface{}) (RuleParams, error)
|
||||||
argNames map[string]bool
|
argNames map[string]bool
|
||||||
scope_ *basicScope
|
scope_ *basicScope
|
||||||
fullName_ string
|
|
||||||
sync.Mutex // protects scope_ during lazy creation
|
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 {
|
func (r *ruleFunc) fullName(pkgNames map[*packageContext]string) string {
|
||||||
if r.fullName_ != "" {
|
|
||||||
return r.fullName_
|
|
||||||
}
|
|
||||||
return packageNamespacePrefix(pkgNames[r.pctx]) + r.name_
|
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) {
|
func (r *ruleFunc) def(config interface{}) (*ruleDef, error) {
|
||||||
params, err := r.paramsFunc(config)
|
params, err := r.paramsFunc(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -939,10 +883,6 @@ func (r *builtinRule) fullName(pkgNames map[*packageContext]string) string {
|
||||||
return r.name_
|
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) {
|
func (r *builtinRule) def(config interface{}) (*ruleDef, error) {
|
||||||
return nil, errRuleIsBuiltin
|
return nil, errRuleIsBuiltin
|
||||||
}
|
}
|
||||||
|
|
49
scope.go
49
scope.go
|
@ -28,7 +28,6 @@ type Variable interface {
|
||||||
packageContext() *packageContext
|
packageContext() *packageContext
|
||||||
name() string // "foo"
|
name() string // "foo"
|
||||||
fullName(pkgNames map[*packageContext]string) string // "pkg.foo" or "path.to.pkg.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)
|
value(ctx VariableFuncContext, config interface{}) (*ninjaString, error)
|
||||||
String() string
|
String() string
|
||||||
}
|
}
|
||||||
|
@ -39,7 +38,6 @@ type Pool interface {
|
||||||
packageContext() *packageContext
|
packageContext() *packageContext
|
||||||
name() string // "foo"
|
name() string // "foo"
|
||||||
fullName(pkgNames map[*packageContext]string) string // "pkg.foo" or "path.to.pkg.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)
|
def(config interface{}) (*poolDef, error)
|
||||||
String() string
|
String() string
|
||||||
}
|
}
|
||||||
|
@ -50,7 +48,6 @@ type Rule interface {
|
||||||
packageContext() *packageContext
|
packageContext() *packageContext
|
||||||
name() string // "foo"
|
name() string // "foo"
|
||||||
fullName(pkgNames map[*packageContext]string) string // "pkg.foo" or "path.to.pkg.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)
|
def(config interface{}) (*ruleDef, error)
|
||||||
scope() *basicScope
|
scope() *basicScope
|
||||||
isArg(argName string) bool
|
isArg(argName string) bool
|
||||||
|
@ -369,10 +366,6 @@ func (l *localVariable) fullName(pkgNames map[*packageContext]string) string {
|
||||||
return l.fullName_
|
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) {
|
func (l *localVariable) value(VariableFuncContext, interface{}) (*ninjaString, error) {
|
||||||
return l.value_, nil
|
return l.value_, nil
|
||||||
}
|
}
|
||||||
|
@ -401,10 +394,6 @@ func (l *localRule) fullName(pkgNames map[*packageContext]string) string {
|
||||||
return l.fullName_
|
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) {
|
func (l *localRule) def(interface{}) (*ruleDef, error) {
|
||||||
return l.def_, nil
|
return l.def_, nil
|
||||||
}
|
}
|
||||||
|
@ -420,3 +409,41 @@ func (r *localRule) isArg(argName string) bool {
|
||||||
func (r *localRule) String() string {
|
func (r *localRule) String() string {
|
||||||
return "<local rule>:" + r.fullName_
|
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