diff --git a/android/writedocs.go b/android/writedocs.go index 9737030e0..7262ad810 100644 --- a/android/writedocs.go +++ b/android/writedocs.go @@ -53,15 +53,19 @@ func (c *docsSingleton) GenerateBuildActions(ctx SingletonContext) { primaryBuilder := primaryBuilderPath(ctx) soongDocs := ctx.Rule(pctx, "soongDocs", blueprint.RuleParams{ - Command: fmt.Sprintf("%s --soong_docs %s %s", + Command: fmt.Sprintf("rm -f ${outDir}/* && %s --soong_docs %s %s", primaryBuilder.String(), docsFile.String(), strings.Join(os.Args[1:], " ")), CommandDeps: []string{primaryBuilder.String()}, Description: fmt.Sprintf("%s docs $out", primaryBuilder.Base()), - }) + }, + "outDir") ctx.Build(pctx, BuildParams{ Rule: soongDocs, Output: docsFile, + Args: map[string]string{ + "outDir": PathForOutput(ctx, "docs").String(), + }, }) // Add a phony target for building the documentation diff --git a/cmd/soong_build/writedocs.go b/cmd/soong_build/writedocs.go index 74c854a39..de2182fe2 100644 --- a/cmd/soong_build/writedocs.go +++ b/cmd/soong_build/writedocs.go @@ -19,6 +19,7 @@ import ( "bytes" "html/template" "io/ioutil" + "path/filepath" "reflect" "sort" @@ -26,6 +27,11 @@ import ( "github.com/google/blueprint/bootstrap/bpdoc" ) +type perPackageTemplateData struct { + Name string + Modules []moduleTypeTemplateData +} + type moduleTypeTemplateData struct { Name string Synopsis string @@ -44,22 +50,7 @@ var propertyRank = map[string]int{ } // For each module type, extract its documentation and convert it to the template data. -func moduleTypeDocsToTemplates(ctx *android.Context) ([]moduleTypeTemplateData, error) { - moduleTypeFactories := android.ModuleTypeFactories() - bpModuleTypeFactories := make(map[string]reflect.Value) - for moduleType, factory := range moduleTypeFactories { - bpModuleTypeFactories[moduleType] = reflect.ValueOf(factory) - } - - packages, err := bootstrap.ModuleTypeDocs(ctx.Context, bpModuleTypeFactories) - if err != nil { - return []moduleTypeTemplateData{}, err - } - var moduleTypeList []*bpdoc.ModuleType - for _, pkg := range packages { - moduleTypeList = append(moduleTypeList, pkg.ModuleTypes...) - } - +func moduleTypeDocsToTemplates(moduleTypeList []*bpdoc.ModuleType) []moduleTypeTemplateData { result := make([]moduleTypeTemplateData, 0) // Combine properties from all PropertyStruct's and reorder them -- first the ones @@ -101,39 +92,121 @@ func moduleTypeDocsToTemplates(ctx *android.Context) ([]moduleTypeTemplateData, result = append(result, item) } sort.Slice(result, func(i, j int) bool { return result[i].Name < result[j].Name }) - return result, err + return result } func writeDocs(ctx *android.Context, filename string) error { - buf := &bytes.Buffer{} + moduleTypeFactories := android.ModuleTypeFactories() + bpModuleTypeFactories := make(map[string]reflect.Value) + for moduleType, factory := range moduleTypeFactories { + bpModuleTypeFactories[moduleType] = reflect.ValueOf(factory) + } - // We need a module name getter/setter function because I couldn't - // find a way to keep it in a variable defined within the template. - currentModuleName := "" - data, err := moduleTypeDocsToTemplates(ctx) + packages, err := bootstrap.ModuleTypeDocs(ctx.Context, bpModuleTypeFactories) if err != nil { return err } - tmpl, err := template.New("file").Funcs(map[string]interface{}{ - "setModule": func(moduleName string) string { - currentModuleName = moduleName - return "" - }, - "getModule": func() string { - return currentModuleName - }, - }).Parse(fileTemplate) + + // Produce the top-level, package list page first. + tmpl, err := template.New("file").Parse(packageListTemplate) + if err != nil { + return err + } + buf := &bytes.Buffer{} if err == nil { - err = tmpl.Execute(buf, data) + err = tmpl.Execute(buf, packages) } if err == nil { err = ioutil.WriteFile(filename, buf.Bytes(), 0666) } + + // Now, produce per-package module lists with detailed information. + for _, pkg := range packages { + // We need a module name getter/setter function because I couldn't + // find a way to keep it in a variable defined within the template. + currentModuleName := "" + tmpl, err := template.New("file").Funcs(map[string]interface{}{ + "setModule": func(moduleName string) string { + currentModuleName = moduleName + return "" + }, + "getModule": func() string { + return currentModuleName + }, + }).Parse(perPackageTemplate) + if err != nil { + return err + } + buf := &bytes.Buffer{} + modules := moduleTypeDocsToTemplates(pkg.ModuleTypes) + data := perPackageTemplateData{Name: pkg.Name, Modules: modules} + err = tmpl.Execute(buf, data) + if err != nil { + return err + } + pkgFileName := filepath.Join(filepath.Dir(filename), pkg.Name+".html") + err = ioutil.WriteFile(pkgFileName, buf.Bytes(), 0666) + if err != nil { + return err + } + } return err } +// TODO(jungjw): Consider ordering by name. const ( - fileTemplate = ` + packageListTemplate = ` + + +Build Docs + + + + +
+

Soong Modules Reference

+The latest versions of Android use the Soong build system, which greatly simplifies build +configuration over the previous Make-based system. This site contains the generated reference +files for the Soong build system. + + + + + + + + + + {{range $pkg := .}} + + + + + {{end}} + +
PackageModule types
{{.Path}} + {{range $i, $mod := .ModuleTypes}}{{if $i}}, {{end}}{{$mod.Name}}{{end}} +
+
+ + +` +) + +const ( + perPackageTemplate = ` Build Docs @@ -174,21 +247,13 @@ li a:hover:not(.active) { {{- /* Fixed sidebar with module types */ -}} {{/* Main panel with H1 section per module type */}}
-

Soong Modules Reference

-The latest versions of Android use the Soong build system, which greatly simplifies build -configuration over the previous Make-based system. This site contains the generated reference -files for the Soong build system. -

-See the Android Build System -description for an overview of Soong and examples for its use. - -{{range $imodule, $moduleType := .}} +{{range $moduleType := .Modules}} {{setModule $moduleType.Name}}

{{$moduleType.Name}}

@@ -225,7 +290,6 @@ description for an overview of Soong and examples for its use. {{- end}} {{- end -}} {{- end -}} -