package bootstrap import ( "bytes" "fmt" "html/template" "io/ioutil" "path/filepath" "reflect" "github.com/google/blueprint" "github.com/google/blueprint/bootstrap/bpdoc" "github.com/google/blueprint/pathtools" ) // ModuleTypeDocs returns a list of bpdoc.ModuleType objects that contain information relevant // to generating documentation for module types supported by the primary builder. func ModuleTypeDocs(ctx *blueprint.Context, config interface{}, factories map[string]reflect.Value) ([]*bpdoc.Package, error) { // Find the module that's marked as the "primary builder", which means it's // creating the binary that we'll use to generate the non-bootstrap // build.ninja file. var primaryBuilders []*goBinary var minibp *goBinary ctx.VisitAllModulesIf(isBootstrapBinaryModule, func(module blueprint.Module) { binaryModule := module.(*goBinary) if binaryModule.properties.PrimaryBuilder { primaryBuilders = append(primaryBuilders, binaryModule) } if ctx.ModuleName(binaryModule) == "minibp" { minibp = binaryModule } }) if minibp == nil { panic("missing minibp") } var primaryBuilder *goBinary switch len(primaryBuilders) { case 0: // If there's no primary builder module then that means we'll use minibp // as the primary builder. primaryBuilder = minibp case 1: primaryBuilder = primaryBuilders[0] default: return nil, fmt.Errorf("multiple primary builder modules present") } pkgFiles := make(map[string][]string) ctx.VisitDepsDepthFirst(primaryBuilder, func(module blueprint.Module) { switch m := module.(type) { case (*goPackage): pkgFiles[m.properties.PkgPath] = pathtools.PrefixPaths(m.properties.Srcs, filepath.Join(config.(BootstrapConfig).SrcDir(), ctx.ModuleDir(m))) default: panic(fmt.Errorf("unknown dependency type %T", module)) } }) mergedFactories := make(map[string]reflect.Value) for moduleType, factory := range factories { mergedFactories[moduleType] = factory } for moduleType, factory := range ctx.ModuleTypeFactories() { if _, exists := mergedFactories[moduleType]; !exists { mergedFactories[moduleType] = reflect.ValueOf(factory) } } return bpdoc.AllPackages(pkgFiles, mergedFactories, ctx.ModuleTypePropertyStructs()) } func writeDocs(ctx *blueprint.Context, config interface{}, filename string) error { moduleTypeList, err := ModuleTypeDocs(ctx, config, nil) if err != nil { return err } buf := &bytes.Buffer{} unique := 0 tmpl, err := template.New("file").Funcs(map[string]interface{}{ "unique": func() int { unique++ return unique }}).Parse(fileTemplate) if err != nil { return err } err = tmpl.Execute(buf, moduleTypeList) if err != nil { return err } err = ioutil.WriteFile(filename, buf.Bytes(), 0666) if err != nil { return err } return nil } const ( fileTemplate = ` Build Docs

Build Docs

{{range .}}

{{.Text}}

{{range .ModuleTypes}} {{ $collapseIndex := unique }}

{{.Text}}

{{range .PropertyStructs}}

{{.Text}}

{{template "properties" .Properties}} {{end}}
{{end}} {{end}}
{{define "properties"}}
{{range .}} {{$collapseIndex := unique}} {{if .Properties}}

{{.Text}}

{{range .OtherTexts}}

{{.}}

{{end}} {{template "properties" .Properties}}
{{else}}

{{.Name}}{{range .OtherNames}}, {{.}}{{end}}

{{.Text}}

{{range .OtherTexts}}

{{.}}

{{end}}

Type: {{.Type}}

{{if .Default}}

Default: {{.Default}}

{{end}}
{{end}} {{end}}
{{end}} ` )