Add support for dependency tags

Primary builder logic is becoming complicated due to the two pass nature
of mutators that add dependencies and GenerateBuildActions that handle
the dependencies.  The reason why the dependency was added is lost by
the time GenerateBuildActions is called, resulting in build logic that
has to recreate all the dependencies and try to match them up to the
modules returned by VisitDirectDeps.

Change the API of AddDependency to take a DependencyTag interface, which
is satisifed by anything that embeds BaseDependencyTag.  Mutators and
GenerateBuildActions that call VisitDirectDeps can pass each Module to
ctx.OtherModuleDependencyTag to retreive the DependencyTag that was
passed when adding the dependency.

Change-Id: I0814dcd26d1670302d340b77e8dc8704ed7b60bf
This commit is contained in:
Colin Cross 2016-04-11 15:47:28 -07:00
parent 910242b9a6
commit 2c1f3d1b28
3 changed files with 151 additions and 139 deletions

View file

@ -143,7 +143,7 @@ func propagateStageBootstrap(mctx blueprint.TopDownMutatorContext) {
func pluginDeps(ctx blueprint.BottomUpMutatorContext) {
if pkg, ok := ctx.Module().(*goPackage); ok {
for _, plugin := range pkg.properties.PluginFor {
ctx.AddReverseDependency(ctx.Module(), plugin)
ctx.AddReverseDependency(ctx.Module(), nil, plugin)
}
}
}

View file

@ -140,7 +140,7 @@ type moduleInfo struct {
moduleProperties []interface{}
// set during ResolveDependencies
directDeps []*moduleInfo
directDeps []depInfo
missingDeps []string
// set during updateDependencies
@ -157,6 +157,11 @@ type moduleInfo struct {
actionDefs localBuildActions
}
type depInfo struct {
module *moduleInfo
tag DependencyTag
}
func (module *moduleInfo) String() string {
s := fmt.Sprintf("module %q", module.properties.Name)
if module.variantName != "" {
@ -960,7 +965,7 @@ func (c *Context) createVariations(origModule *moduleInfo, mutatorName string,
m := *origModule
newModule := &m
newModule.directDeps = append([]*moduleInfo(nil), origModule.directDeps...)
newModule.directDeps = append([]depInfo{}, origModule.directDeps...)
newModule.logicModule = newLogicModule
newModule.variant = newVariant
newModule.dependencyVariant = origModule.dependencyVariant.clone()
@ -997,9 +1002,9 @@ func (c *Context) convertDepsToVariation(module *moduleInfo,
mutatorName, variationName string) (errs []error) {
for i, dep := range module.directDeps {
if dep.logicModule == nil {
if dep.module.logicModule == nil {
var newDep *moduleInfo
for _, m := range dep.splitModules {
for _, m := range dep.module.splitModules {
if m.variant[mutatorName] == variationName {
newDep = m
break
@ -1008,12 +1013,12 @@ func (c *Context) convertDepsToVariation(module *moduleInfo,
if newDep == nil {
errs = append(errs, &Error{
Err: fmt.Errorf("failed to find variation %q for module %q needed by %q",
variationName, dep.properties.Name, module.properties.Name),
variationName, dep.module.properties.Name, module.properties.Name),
Pos: module.pos,
})
continue
}
module.directDeps[i] = newDep
module.directDeps[i].module = newDep
}
}
@ -1137,7 +1142,7 @@ func (c *Context) ResolveDependencies(config interface{}) []error {
// AddVariationDependencies on DynamicDependencyModuleContext. Otherwise it
// is simply those names listed in its "deps" property.
func blueprintDepsMutator(ctx BottomUpMutatorContext) {
ctx.AddDependency(ctx.Module(), ctx.moduleInfo().properties.Deps...)
ctx.AddDependency(ctx.Module(), nil, ctx.moduleInfo().properties.Deps...)
if dynamicDepender, ok := ctx.Module().(DynamicDependerModule); ok {
func() {
@ -1152,7 +1157,7 @@ func blueprintDepsMutator(ctx BottomUpMutatorContext) {
return
}
ctx.AddDependency(ctx.Module(), dynamicDeps...)
ctx.AddDependency(ctx.Module(), nil, dynamicDeps...)
}()
}
}
@ -1173,7 +1178,7 @@ func (c *Context) findMatchingVariant(module *moduleInfo, group *moduleGroup) *m
return nil
}
func (c *Context) addDependency(module *moduleInfo, depName string) []error {
func (c *Context) addDependency(module *moduleInfo, tag DependencyTag, depName string) []error {
if depName == module.properties.Name {
return []error{&Error{
Err: fmt.Errorf("%q depends on itself", depName),
@ -1181,7 +1186,7 @@ func (c *Context) addDependency(module *moduleInfo, depName string) []error {
}}
}
depInfo, ok := c.moduleGroups[depName]
depGroup, ok := c.moduleGroups[depName]
if !ok {
if c.allowMissingDependencies {
module.missingDeps = append(module.missingDeps, depName)
@ -1194,20 +1199,20 @@ func (c *Context) addDependency(module *moduleInfo, depName string) []error {
}}
}
for _, m := range module.directDeps {
if m.group == depInfo {
return nil
if m := c.findMatchingVariant(module, depGroup); m != nil {
for _, dep := range module.directDeps {
if m == dep.module {
// TODO(ccross): what if adding a dependency with a different tag?
return nil
}
}
}
if m := c.findMatchingVariant(module, depInfo); m != nil {
module.directDeps = append(module.directDeps, m)
module.directDeps = append(module.directDeps, depInfo{m, tag})
return nil
}
return []error{&Error{
Err: fmt.Errorf("dependency %q of %q missing variant %q",
depInfo.modules[0].properties.Name, module.properties.Name,
depGroup.modules[0].properties.Name, module.properties.Name,
c.prettyPrintVariant(module.dependencyVariant)),
Pos: module.pos,
}}
@ -1243,9 +1248,9 @@ func (c *Context) findReverseDependency(module *moduleInfo, destName string) (*m
}
func (c *Context) addVariationDependency(module *moduleInfo, variations []Variation,
depName string, far bool) []error {
tag DependencyTag, depName string, far bool) []error {
depInfo, ok := c.moduleGroups[depName]
depGroup, ok := c.moduleGroups[depName]
if !ok {
if c.allowMissingDependencies {
module.missingDeps = append(module.missingDeps, depName)
@ -1271,7 +1276,7 @@ func (c *Context) addVariationDependency(module *moduleInfo, variations []Variat
newVariant[v.Mutator] = v.Variation
}
for _, m := range depInfo.modules {
for _, m := range depGroup.modules {
var found bool
if far {
found = m.variant.subset(newVariant)
@ -1288,20 +1293,20 @@ func (c *Context) addVariationDependency(module *moduleInfo, variations []Variat
// AddVariationDependency allows adding a dependency on itself, but only if
// that module is earlier in the module list than this one, since we always
// run GenerateBuildActions in order for the variants of a module
if depInfo == module.group && beforeInModuleList(module, m, module.group.modules) {
if depGroup == module.group && beforeInModuleList(module, m, module.group.modules) {
return []error{&Error{
Err: fmt.Errorf("%q depends on later version of itself", depName),
Pos: module.pos,
}}
}
module.directDeps = append(module.directDeps, m)
module.directDeps = append(module.directDeps, depInfo{m, tag})
return nil
}
}
return []error{&Error{
Err: fmt.Errorf("dependency %q of %q missing variant %q",
depInfo.modules[0].properties.Name, module.properties.Name,
depGroup.modules[0].properties.Name, module.properties.Name,
c.prettyPrintVariant(newVariant)),
Pos: module.pos,
}}
@ -1403,7 +1408,7 @@ func (c *Context) updateDependencies() (errs []error) {
}
for _, dep := range module.directDeps {
deps[dep] = true
deps[dep.module] = true
}
module.reverseDeps = []*moduleInfo{}
@ -1641,7 +1646,7 @@ func (c *Context) runTopDownMutator(config interface{},
func (c *Context) runBottomUpMutator(config interface{},
name string, mutator BottomUpMutator) (errs []error) {
reverseDeps := make(map[*moduleInfo][]*moduleInfo)
reverseDeps := make(map[*moduleInfo][]depInfo)
for _, module := range c.modulesSorted {
newModules := make([]*moduleInfo, 0, 1)
@ -1682,8 +1687,8 @@ func (c *Context) runBottomUpMutator(config interface{},
// Fix up any remaining dependencies on modules that were split into variants
// by replacing them with the first variant
for i, dep := range module.directDeps {
if dep.logicModule == nil {
module.directDeps[i] = dep.splitModules[0]
if dep.module.logicModule == nil {
module.directDeps[i].module = dep.module.splitModules[0]
}
}
@ -1697,7 +1702,7 @@ func (c *Context) runBottomUpMutator(config interface{},
}
for module, deps := range reverseDeps {
sort.Sort(moduleSorter(deps))
sort.Sort(depSorter(deps))
module.directDeps = append(module.directDeps, deps...)
}
@ -1963,12 +1968,12 @@ func (c *Context) walkDeps(topModule *moduleInfo,
var walk func(module *moduleInfo)
walk = func(module *moduleInfo) {
for _, moduleDep := range module.directDeps {
if !visited[moduleDep] {
visited[moduleDep] = true
visiting = moduleDep
if visit(moduleDep.logicModule, module.logicModule) {
walk(moduleDep)
for _, dep := range module.directDeps {
if !visited[dep.module] {
visited[dep.module] = true
visiting = dep.module
if visit(dep.module.logicModule, module.logicModule) {
walk(dep.module)
}
}
}
@ -1993,9 +1998,9 @@ func (c *Context) visitDepsDepthFirst(topModule *moduleInfo, visit func(Module))
var walk func(module *moduleInfo)
walk = func(module *moduleInfo) {
visited[module] = true
for _, moduleDep := range module.directDeps {
if !visited[moduleDep] {
walk(moduleDep)
for _, dep := range module.directDeps {
if !visited[dep.module] {
walk(dep.module)
}
}
@ -2024,9 +2029,9 @@ func (c *Context) visitDepsDepthFirstIf(topModule *moduleInfo, pred func(Module)
var walk func(module *moduleInfo)
walk = func(module *moduleInfo) {
visited[module] = true
for _, moduleDep := range module.directDeps {
if !visited[moduleDep] {
walk(moduleDep)
for _, dep := range module.directDeps {
if !visited[dep.module] {
walk(dep.module)
}
}
@ -2041,40 +2046,6 @@ func (c *Context) visitDepsDepthFirstIf(topModule *moduleInfo, pred func(Module)
walk(topModule)
}
func (c *Context) visitDirectDeps(module *moduleInfo, visit func(Module)) {
var dep *moduleInfo
defer func() {
if r := recover(); r != nil {
panic(newPanicErrorf(r, "VisitDirectDeps(%s, %s) for dependency %s",
module, funcName(visit), dep))
}
}()
for _, dep = range module.directDeps {
visit(dep.logicModule)
}
}
func (c *Context) visitDirectDepsIf(module *moduleInfo, pred func(Module) bool,
visit func(Module)) {
var dep *moduleInfo
defer func() {
if r := recover(); r != nil {
panic(newPanicErrorf(r, "VisitDirectDepsIf(%s, %s, %s) for dependency %s",
module, funcName(pred), funcName(visit), dep))
}
}()
for _, dep = range module.directDeps {
if pred(dep.logicModule) {
visit(dep.logicModule)
}
}
}
func (c *Context) sortedModuleNames() []string {
if c.cachedSortedModuleNames == nil {
c.cachedSortedModuleNames = make([]string, 0, len(c.moduleGroups))
@ -2693,6 +2664,26 @@ func (c *Context) writeGlobalRules(nw *ninjaWriter) error {
return nil
}
type depSorter []depInfo
func (s depSorter) Len() int {
return len(s)
}
func (s depSorter) Less(i, j int) bool {
iName := s[i].module.properties.Name
jName := s[j].module.properties.Name
if iName == jName {
iName = s[i].module.variantName
jName = s[j].module.variantName
}
return iName < jName
}
func (s depSorter) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
type moduleSorter []*moduleInfo
func (s moduleSorter) Len() int {

View file

@ -129,6 +129,7 @@ type ModuleContext interface {
OtherModuleName(m Module) string
OtherModuleErrorf(m Module, fmt string, args ...interface{})
OtherModuleDependencyTag(m Module) DependencyTag
VisitDirectDeps(visit func(Module))
VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
@ -154,10 +155,11 @@ type ModuleContext interface {
var _ BaseModuleContext = (*baseModuleContext)(nil)
type baseModuleContext struct {
context *Context
config interface{}
module *moduleInfo
errs []error
context *Context
config interface{}
module *moduleInfo
errs []error
visiting depInfo
}
func (d *baseModuleContext) moduleInfo() *moduleInfo {
@ -236,12 +238,12 @@ type moduleContext struct {
handledMissingDeps bool
}
func (m *moduleContext) OtherModuleName(logicModule Module) string {
func (m *baseModuleContext) OtherModuleName(logicModule Module) string {
module := m.context.moduleInfo[logicModule]
return module.properties.Name
}
func (m *moduleContext) OtherModuleErrorf(logicModule Module, format string,
func (m *baseModuleContext) OtherModuleErrorf(logicModule Module, format string,
args ...interface{}) {
module := m.context.moduleInfo[logicModule]
@ -251,25 +253,64 @@ func (m *moduleContext) OtherModuleErrorf(logicModule Module, format string,
})
}
func (m *moduleContext) VisitDirectDeps(visit func(Module)) {
m.context.visitDirectDeps(m.module, visit)
func (m *baseModuleContext) OtherModuleDependencyTag(logicModule Module) DependencyTag {
// fast path for calling OtherModuleDependencyTag from inside VisitDirectDeps
if logicModule == m.visiting.module.logicModule {
return m.visiting.tag
}
for _, dep := range m.module.directDeps {
if dep.module.logicModule == logicModule {
return dep.tag
}
}
return nil
}
func (m *moduleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
m.context.visitDirectDepsIf(m.module, pred, visit)
func (m *baseModuleContext) VisitDirectDeps(visit func(Module)) {
defer func() {
if r := recover(); r != nil {
panic(newPanicErrorf(r, "VisitDirectDeps(%s, %s) for dependency %s",
m.module, funcName(visit), m.visiting.module))
}
}()
for _, dep := range m.module.directDeps {
m.visiting = dep
visit(dep.module.logicModule)
}
m.visiting = depInfo{}
}
func (m *moduleContext) VisitDepsDepthFirst(visit func(Module)) {
func (m *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
defer func() {
if r := recover(); r != nil {
panic(newPanicErrorf(r, "VisitDirectDepsIf(%s, %s, %s) for dependency %s",
m.module, funcName(pred), funcName(visit), m.visiting.module))
}
}()
for _, dep := range m.module.directDeps {
m.visiting = dep
if pred(dep.module.logicModule) {
visit(dep.module.logicModule)
}
}
m.visiting = depInfo{}
}
func (m *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
m.context.visitDepsDepthFirst(m.module, visit)
}
func (m *moduleContext) VisitDepsDepthFirstIf(pred func(Module) bool,
func (m *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool,
visit func(Module)) {
m.context.visitDepsDepthFirstIf(m.module, pred, visit)
}
func (m *moduleContext) WalkDeps(visit func(Module, Module) bool) {
func (m *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
m.context.walkDeps(m.module, visit)
}
@ -342,7 +383,7 @@ func (m *moduleContext) GetMissingDependencies() []string {
type mutatorContext struct {
baseModuleContext
name string
reverseDeps map[*moduleInfo][]*moduleInfo
reverseDeps map[*moduleInfo][]depInfo
}
type baseMutatorContext interface {
@ -363,6 +404,7 @@ type TopDownMutatorContext interface {
OtherModuleName(m Module) string
OtherModuleErrorf(m Module, fmt string, args ...interface{})
OtherModuleDependencyTag(m Module) DependencyTag
VisitDirectDeps(visit func(Module))
VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
@ -374,13 +416,13 @@ type TopDownMutatorContext interface {
type BottomUpMutatorContext interface {
baseMutatorContext
AddDependency(module Module, name ...string)
AddReverseDependency(module Module, name string)
AddDependency(module Module, tag DependencyTag, name ...string)
AddReverseDependency(module Module, tag DependencyTag, name string)
CreateVariations(...string) []Module
CreateLocalVariations(...string) []Module
SetDependencyVariation(string)
AddVariationDependencies([]Variation, ...string)
AddFarVariationDependencies([]Variation, ...string)
AddVariationDependencies([]Variation, DependencyTag, ...string)
AddFarVariationDependencies([]Variation, DependencyTag, ...string)
}
// A Mutator function is called for each Module, and can use
@ -396,6 +438,22 @@ type TopDownMutator func(mctx TopDownMutatorContext)
type BottomUpMutator func(mctx BottomUpMutatorContext)
type EarlyMutator func(mctx EarlyMutatorContext)
// DependencyTag is an interface to an arbitrary object that embeds BaseDependencyTag. It can be
// used to transfer information on a dependency between the mutator that called AddDependency
// and the GenerateBuildActions method. Variants created by CreateVariations have a copy of the
// interface (pointing to the same concrete object) from their original module.
type DependencyTag interface {
dependencyTag(DependencyTag)
}
type BaseDependencyTag struct {
}
func (BaseDependencyTag) dependencyTag(DependencyTag) {
}
var _ DependencyTag = BaseDependencyTag{}
// Split a module into mulitple variants, one for each name in the variationNames
// parameter. It returns a list of new modules in the same order as the variationNames
// list.
@ -456,9 +514,9 @@ func (mctx *mutatorContext) Module() Module {
// Add a dependency to the given module.
// Does not affect the ordering of the current mutator pass, but will be ordered
// correctly for all future mutator passes.
func (mctx *mutatorContext) AddDependency(module Module, deps ...string) {
func (mctx *mutatorContext) AddDependency(module Module, tag DependencyTag, deps ...string) {
for _, dep := range deps {
errs := mctx.context.addDependency(mctx.context.moduleInfo[module], dep)
errs := mctx.context.addDependency(mctx.context.moduleInfo[module], tag, dep)
if len(errs) > 0 {
mctx.errs = append(mctx.errs, errs...)
}
@ -470,7 +528,7 @@ func (mctx *mutatorContext) AddDependency(module Module, deps ...string) {
// correctly for all future mutator passes. All reverse dependencies for a destination module are
// collected until the end of the mutator pass, sorted by name, and then appended to the destination
// module's dependency list.
func (mctx *mutatorContext) AddReverseDependency(module Module, destName string) {
func (mctx *mutatorContext) AddReverseDependency(module Module, tag DependencyTag, destName string) {
destModule, errs := mctx.context.findReverseDependency(mctx.context.moduleInfo[module], destName)
if len(errs) > 0 {
mctx.errs = append(mctx.errs, errs...)
@ -478,18 +536,18 @@ func (mctx *mutatorContext) AddReverseDependency(module Module, destName string)
}
mctx.reverseDeps[destModule] = append(mctx.reverseDeps[destModule],
mctx.context.moduleInfo[module])
depInfo{mctx.context.moduleInfo[module], tag})
}
// AddVariationDependencies adds deps as dependencies of the current module, but uses the variations
// argument to select which variant of the dependency to use. A variant of the dependency must
// exist that matches the all of the non-local variations of the current module, plus the variations
// argument.
func (mctx *mutatorContext) AddVariationDependencies(variations []Variation,
func (mctx *mutatorContext) AddVariationDependencies(variations []Variation, tag DependencyTag,
deps ...string) {
for _, dep := range deps {
errs := mctx.context.addVariationDependency(mctx.module, variations, dep, false)
errs := mctx.context.addVariationDependency(mctx.module, variations, tag, dep, false)
if len(errs) > 0 {
mctx.errs = append(mctx.errs, errs...)
}
@ -503,50 +561,13 @@ func (mctx *mutatorContext) AddVariationDependencies(variations []Variation,
//
// Unlike AddVariationDependencies, the variations of the current module are ignored - the
// depdendency only needs to match the supplied variations.
func (mctx *mutatorContext) AddFarVariationDependencies(variations []Variation,
func (mctx *mutatorContext) AddFarVariationDependencies(variations []Variation, tag DependencyTag,
deps ...string) {
for _, dep := range deps {
errs := mctx.context.addVariationDependency(mctx.module, variations, dep, true)
errs := mctx.context.addVariationDependency(mctx.module, variations, tag, dep, true)
if len(errs) > 0 {
mctx.errs = append(mctx.errs, errs...)
}
}
}
func (mctx *mutatorContext) OtherModuleName(logicModule Module) string {
module := mctx.context.moduleInfo[logicModule]
return module.properties.Name
}
func (mctx *mutatorContext) OtherModuleErrorf(logicModule Module, format string,
args ...interface{}) {
module := mctx.context.moduleInfo[logicModule]
mctx.errs = append(mctx.errs, &Error{
Err: fmt.Errorf(format, args...),
Pos: module.pos,
})
}
func (mctx *mutatorContext) VisitDirectDeps(visit func(Module)) {
mctx.context.visitDirectDeps(mctx.module, visit)
}
func (mctx *mutatorContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
mctx.context.visitDirectDepsIf(mctx.module, pred, visit)
}
func (mctx *mutatorContext) VisitDepsDepthFirst(visit func(Module)) {
mctx.context.visitDepsDepthFirst(mctx.module, visit)
}
func (mctx *mutatorContext) VisitDepsDepthFirstIf(pred func(Module) bool,
visit func(Module)) {
mctx.context.visitDepsDepthFirstIf(mctx.module, pred, visit)
}
func (mctx *mutatorContext) WalkDeps(visit func(Module, Module) bool) {
mctx.context.walkDeps(mctx.module, visit)
}