Add VariableFuncContext argument to VariableFuncs
Add a VariableFuncContext argument to VariableFuncs that implements GlobWithDeps. This will allow Soong to use optimized glob dependencies in VariableFuncs. Bug: 257079828 Test: no dependencies on directories in build.ninja.d Change-Id: Iee5fc9c9ae3087662a5d1a3d7323a87462299205
This commit is contained in:
parent
2a9208713e
commit
1b457a5e10
7 changed files with 41 additions and 17 deletions
|
@ -149,7 +149,7 @@ var (
|
||||||
},
|
},
|
||||||
"depfile")
|
"depfile")
|
||||||
|
|
||||||
_ = pctx.VariableFunc("ToolDir", func(config interface{}) (string, error) {
|
_ = pctx.VariableFunc("ToolDir", func(ctx blueprint.VariableFuncContext, config interface{}) (string, error) {
|
||||||
return config.(BootstrapConfig).HostToolDir(), nil
|
return config.(BootstrapConfig).HostToolDir(), nil
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
|
@ -25,7 +25,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func bootstrapVariable(name string, value func(BootstrapConfig) string) blueprint.Variable {
|
func bootstrapVariable(name string, value func(BootstrapConfig) string) blueprint.Variable {
|
||||||
return pctx.VariableFunc(name, func(config interface{}) (string, error) {
|
return pctx.VariableFunc(name, func(ctx blueprint.VariableFuncContext, config interface{}) (string, error) {
|
||||||
c, ok := config.(BootstrapConfig)
|
c, ok := config.(BootstrapConfig)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Bootstrap rules were passed a configuration that does not include theirs, config=%q",
|
panic(fmt.Sprintf("Bootstrap rules were passed a configuration that does not include theirs, config=%q",
|
||||||
|
|
|
@ -44,7 +44,7 @@ import (
|
||||||
// in a build failure with a "missing and no known rule to make it" error.
|
// in a build failure with a "missing and no known rule to make it" error.
|
||||||
|
|
||||||
var (
|
var (
|
||||||
_ = pctx.VariableFunc("globCmd", func(config interface{}) (string, error) {
|
_ = pctx.VariableFunc("globCmd", func(ctx blueprint.VariableFuncContext, config interface{}) (string, error) {
|
||||||
return filepath.Join(config.(BootstrapConfig).SoongOutDir(), "bpglob"), nil
|
return filepath.Join(config.(BootstrapConfig).SoongOutDir(), "bpglob"), nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1798,7 +1798,7 @@ func (c *Context) resolveDependencies(ctx context.Context, config interface{}) (
|
||||||
pprof.Do(ctx, pprof.Labels("blueprint", "ResolveDependencies"), func(ctx context.Context) {
|
pprof.Do(ctx, pprof.Labels("blueprint", "ResolveDependencies"), func(ctx context.Context) {
|
||||||
c.initProviders()
|
c.initProviders()
|
||||||
|
|
||||||
c.liveGlobals = newLiveTracker(config)
|
c.liveGlobals = newLiveTracker(c, config)
|
||||||
|
|
||||||
deps, errs = c.generateSingletonBuildActions(config, c.preSingletonInfo, c.liveGlobals)
|
deps, errs = c.generateSingletonBuildActions(config, c.preSingletonInfo, c.liveGlobals)
|
||||||
if len(errs) > 0 {
|
if len(errs) > 0 {
|
||||||
|
@ -4413,7 +4413,7 @@ func (c *Context) writeLocalBuildActions(nw *ninjaWriter,
|
||||||
// A localVariable doesn't need the package names or config to
|
// A localVariable doesn't need the package names or config to
|
||||||
// determine its name or value.
|
// determine its name or value.
|
||||||
name := v.fullName(nil)
|
name := v.fullName(nil)
|
||||||
value, err := v.value(nil)
|
value, err := v.value(nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,14 +23,16 @@ import "sync"
|
||||||
type liveTracker struct {
|
type liveTracker struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
config interface{} // Used to evaluate variable, rule, and pool values.
|
config interface{} // Used to evaluate variable, rule, and pool values.
|
||||||
|
ctx *Context // Used to evaluate globs
|
||||||
|
|
||||||
variables map[Variable]ninjaString
|
variables map[Variable]ninjaString
|
||||||
pools map[Pool]*poolDef
|
pools map[Pool]*poolDef
|
||||||
rules map[Rule]*ruleDef
|
rules map[Rule]*ruleDef
|
||||||
}
|
}
|
||||||
|
|
||||||
func newLiveTracker(config interface{}) *liveTracker {
|
func newLiveTracker(ctx *Context, config interface{}) *liveTracker {
|
||||||
return &liveTracker{
|
return &liveTracker{
|
||||||
|
ctx: ctx,
|
||||||
config: config,
|
config: config,
|
||||||
variables: make(map[Variable]ninjaString),
|
variables: make(map[Variable]ninjaString),
|
||||||
pools: make(map[Pool]*poolDef),
|
pools: make(map[Pool]*poolDef),
|
||||||
|
@ -153,7 +155,9 @@ func (l *liveTracker) addPool(p Pool) error {
|
||||||
func (l *liveTracker) addVariable(v Variable) error {
|
func (l *liveTracker) addVariable(v Variable) error {
|
||||||
_, ok := l.variables[v]
|
_, ok := l.variables[v]
|
||||||
if !ok {
|
if !ok {
|
||||||
value, err := v.value(l.config)
|
ctx := &variableFuncContext{l.ctx}
|
||||||
|
|
||||||
|
value, err := v.value(ctx, l.config)
|
||||||
if err == errVariableIsArg {
|
if err == errVariableIsArg {
|
||||||
// This variable is a placeholder for an argument that can be passed
|
// This variable is a placeholder for an argument that can be passed
|
||||||
// to a rule. It has no value and thus doesn't reference any other
|
// to a rule. It has no value and thus doesn't reference any other
|
||||||
|
|
|
@ -59,7 +59,7 @@ type PackageContext interface {
|
||||||
ImportAs(as, pkgPath string)
|
ImportAs(as, pkgPath string)
|
||||||
|
|
||||||
StaticVariable(name, value string) Variable
|
StaticVariable(name, value string) Variable
|
||||||
VariableFunc(name string, f func(config interface{}) (string, error)) Variable
|
VariableFunc(name string, f func(ctx VariableFuncContext, config interface{}) (string, error)) Variable
|
||||||
VariableConfigMethod(name string, method interface{}) Variable
|
VariableConfigMethod(name string, method interface{}) Variable
|
||||||
|
|
||||||
StaticPool(name string, params PoolParams) Pool
|
StaticPool(name string, params PoolParams) Pool
|
||||||
|
@ -304,7 +304,7 @@ func (v *staticVariable) memoizeFullName(pkgNames map[*packageContext]string) {
|
||||||
v.fullName_ = v.fullName(pkgNames)
|
v.fullName_ = v.fullName(pkgNames)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *staticVariable) value(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 {
|
||||||
err = fmt.Errorf("error parsing variable %s value: %s", v, err)
|
err = fmt.Errorf("error parsing variable %s value: %s", v, err)
|
||||||
|
@ -320,10 +320,30 @@ func (v *staticVariable) String() string {
|
||||||
type variableFunc struct {
|
type variableFunc struct {
|
||||||
pctx *packageContext
|
pctx *packageContext
|
||||||
name_ string
|
name_ string
|
||||||
value_ func(interface{}) (string, error)
|
value_ func(VariableFuncContext, interface{}) (string, error)
|
||||||
fullName_ string
|
fullName_ string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VariableFuncContext is passed to VariableFunc functions.
|
||||||
|
type VariableFuncContext interface {
|
||||||
|
// GlobWithDeps returns a list of files and directories that match the
|
||||||
|
// specified pattern but do not match any of the patterns in excludes.
|
||||||
|
// Any directories will have a '/' suffix. It also adds efficient
|
||||||
|
// dependencies to rerun the primary builder whenever a file matching
|
||||||
|
// the pattern as added or removed, without rerunning if a file that
|
||||||
|
// does not match the pattern is added to a searched directory.
|
||||||
|
GlobWithDeps(globPattern string, excludes []string) ([]string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type variableFuncContext struct {
|
||||||
|
context *Context
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *variableFuncContext) GlobWithDeps(pattern string,
|
||||||
|
excludes []string) ([]string, error) {
|
||||||
|
return v.context.glob(pattern, excludes)
|
||||||
|
}
|
||||||
|
|
||||||
// VariableFunc returns a Variable whose value is determined by a function that
|
// VariableFunc returns a Variable whose value is determined by a function that
|
||||||
// takes a config object as input and returns either the variable value or an
|
// takes a config object as input and returns either the variable value or an
|
||||||
// error. It may only be called during a Go package's initialization - either
|
// error. It may only be called during a Go package's initialization - either
|
||||||
|
@ -336,7 +356,7 @@ type variableFunc struct {
|
||||||
// reference other Ninja variables that are visible within the calling Go
|
// reference other Ninja variables that are visible within the calling Go
|
||||||
// package.
|
// package.
|
||||||
func (p *packageContext) VariableFunc(name string,
|
func (p *packageContext) VariableFunc(name string,
|
||||||
f func(config interface{}) (string, error)) Variable {
|
f func(ctx VariableFuncContext, config interface{}) (string, error)) Variable {
|
||||||
|
|
||||||
checkCalledFromInit()
|
checkCalledFromInit()
|
||||||
|
|
||||||
|
@ -382,7 +402,7 @@ func (p *packageContext) VariableConfigMethod(name string,
|
||||||
methodValue := reflect.ValueOf(method)
|
methodValue := reflect.ValueOf(method)
|
||||||
validateVariableMethod(name, methodValue)
|
validateVariableMethod(name, methodValue)
|
||||||
|
|
||||||
fun := func(config interface{}) (string, error) {
|
fun := func(ctx VariableFuncContext, config interface{}) (string, error) {
|
||||||
result := methodValue.Call([]reflect.Value{reflect.ValueOf(config)})
|
result := methodValue.Call([]reflect.Value{reflect.ValueOf(config)})
|
||||||
resultStr := result[0].Interface().(string)
|
resultStr := result[0].Interface().(string)
|
||||||
return resultStr, nil
|
return resultStr, nil
|
||||||
|
@ -420,8 +440,8 @@ func (v *variableFunc) memoizeFullName(pkgNames map[*packageContext]string) {
|
||||||
v.fullName_ = v.fullName(pkgNames)
|
v.fullName_ = v.fullName(pkgNames)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *variableFunc) value(config interface{}) (ninjaString, error) {
|
func (v *variableFunc) value(ctx VariableFuncContext, config interface{}) (ninjaString, error) {
|
||||||
value, err := v.value_(config)
|
value, err := v.value_(ctx, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -484,7 +504,7 @@ func (v *argVariable) memoizeFullName(pkgNames map[*packageContext]string) {
|
||||||
// Nothing to do, full name is known at initialization.
|
// Nothing to do, full name is known at initialization.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *argVariable) value(config interface{}) (ninjaString, error) {
|
func (v *argVariable) value(ctx VariableFuncContext, config interface{}) (ninjaString, error) {
|
||||||
return nil, errVariableIsArg
|
return nil, errVariableIsArg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
4
scope.go
4
scope.go
|
@ -29,7 +29,7 @@ type Variable interface {
|
||||||
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
|
memoizeFullName(pkgNames map[*packageContext]string) // precompute fullName if desired
|
||||||
value(config interface{}) (ninjaString, error)
|
value(ctx VariableFuncContext, config interface{}) (ninjaString, error)
|
||||||
String() string
|
String() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,7 +373,7 @@ func (l *localVariable) memoizeFullName(pkgNames map[*packageContext]string) {
|
||||||
// Nothing to do, full name is known at initialization.
|
// Nothing to do, full name is known at initialization.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *localVariable) value(interface{}) (ninjaString, error) {
|
func (l *localVariable) value(VariableFuncContext, interface{}) (ninjaString, error) {
|
||||||
return l.value_, nil
|
return l.value_, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue