func expandDefault(d string, visited []string) []string {
	var defaults []string
	if len(defaultsMap[d]) > 0 {
		for _, def := range defaultsMap[d] {
			if utils.Find(visited, def) >= 0 {
				panic(fmt.Errorf("Defaults module %s depends upon itself", def))
			}
			defaults = append(defaults, expandDefault(def, append(visited, def))...)
			defaults = append(defaults, def)
		}
	}
	return defaults
}
Take a single defaults module, and recursively expand it to list
all the hierarchical defaults it depends on (not including itself).
It's important that the ordering is maintained.

a
/   \
b       c
/  \     /  \
d    e   f    g

==> d e b f g c

This function is recursive. To prevent getting into an infinite
loop on encountering a cycle, we pass a list of already visited
modules in.
package core
import (
	"fmt"
	"sync"
	"github.com/google/blueprint"
	"github.com/ARM-software/bob-build/internal/utils"
)
type defaults struct {
	moduleBase
	Properties struct {
		Features
		Build
		KernelProps
		Defaults []string
	}
}
func (m *defaults) supportedVariants() []tgtType {
	return []tgtType{tgtTypeHost, tgtTypeTarget}
}
func (m *defaults) disable() {
	panic("disable() called on Default")
}
func (m *defaults) setVariant(variant tgtType) {
	m.Properties.TargetType = variant
}
func (m *defaults) getSplittableProps() *SplittableProps {
	return &m.Properties.SplittableProps
}
func (m *defaults) defaults() []string {
	return m.Properties.Defaults
}
func (m *defaults) build() *Build {
	return &m.Properties.Build
}
func (m *defaults) defaultableProperties() []interface{} {
	return []interface{}{
		&m.Properties.Build.CommonProps,
		&m.Properties.Build.BuildProps,
		&m.Properties.Build.SplittableProps,
		&m.Properties.KernelProps,
	}
}
func (m *defaults) featurableProperties() []interface{} {
	return []interface{}{
		&m.Properties.Build.CommonProps,
		&m.Properties.Build.BuildProps,
		&m.Properties.Build.SplittableProps,
		&m.Properties.KernelProps,
	}
}
func (m *defaults) targetableProperties() []interface{} {
	return []interface{}{
		&m.Properties.Build.CommonProps,
		&m.Properties.Build.BuildProps,
		&m.Properties.Build.SplittableProps,
		&m.Properties.KernelProps,
	}
}
func (m *defaults) features() *Features {
	return &m.Properties.Features
}
func (m *defaults) getTarget() tgtType {
	return m.Properties.TargetType
}
func (m *defaults) getTargetSpecific(variant tgtType) *TargetSpecific {
	return m.Properties.getTargetSpecific(variant)
}
func (m *defaults) processPaths(ctx blueprint.BaseModuleContext, g generatorBackend) {
	m.Properties.Build.processPaths(ctx, g)
	m.Properties.KernelProps.processPaths(ctx)
}
func (m *defaults) GenerateBuildActions(ctx blueprint.ModuleContext) {
}
func (m *defaults) getEscapeProperties() []*[]string {
	return []*[]string{
		&m.Properties.Asflags,
		&m.Properties.Cflags,
		&m.Properties.Conlyflags,
		&m.Properties.Cxxflags,
		&m.Properties.Ldflags}
}
func (m *defaults) getSourceProperties() *SourceProps {
	return &m.Properties.SourceProps
}
func (m *defaults) getMatchSourcePropNames() []string {
	return []string{"Ldflags", "Cflags", "Conlyflags", "Cxxflags"}
}
func defaultsFactory(config *bobConfig) (blueprint.Module, []interface{}) {
	module := &defaults{}
	module.Properties.Features.Init(&config.Properties, CommonProps{}, BuildProps{}, KernelProps{}, SplittableProps{})
	module.Properties.Host.init(&config.Properties, CommonProps{}, BuildProps{}, KernelProps{})
	module.Properties.Target.init(&config.Properties, CommonProps{}, BuildProps{}, KernelProps{})
	return module, []interface{}{&module.Properties, &module.SimpleName.Properties}
}
var defaultDepTag = dependencyTag{name: "default"}
type defaultable interface {
	defaults() []string
	defaultableProperties() []interface{}
}
var _ defaultable = (*defaults)(nil)
var _ moduleWithBuildProps = (*defaults)(nil)
var _ targetSpecificLibrary = (*defaults)(nil)
var _ featurable = (*defaults)(nil)
var _ pathProcessor = (*defaults)(nil)
var _ matchSourceInterface = (*defaults)(nil)
var _ propertyEscapeInterface = (*defaults)(nil)
var (
	defaultsMap     = map[string][]string{}
	defaultsMapLock sync.RWMutex
)
func defaultDepsStage1Mutator(mctx blueprint.BottomUpMutatorContext) {
	if l, ok := mctx.Module().(defaultable); ok {
		defaultsMapLock.Lock()
		defer defaultsMapLock.Unlock()
		defaultsMap[mctx.ModuleName()] = l.defaults()
	}
	if gsc, ok := getGenerateCommon(mctx.Module()); ok {
		if len(gsc.Properties.Flag_defaults) > 0 {
			tgt := gsc.Properties.Target
			if !(tgt == tgtTypeHost || tgt == tgtTypeTarget) {
				panic(fmt.Errorf("Module %s uses flag_defaults '%v' but has invalid target type '%s'",
					mctx.ModuleName(), gsc.Properties.Flag_defaults, tgt))
			}
		}
	}
}