blob: 99df32fb362c1d47f1cb245365f3a76b1041caa5 [file] [log] [blame]
Colin Cross4572edd2015-05-13 14:36:24 -07001package bootstrap
2
3import (
Colin Cross92639f32017-12-11 14:39:41 -08004 "bytes"
Colin Cross4572edd2015-05-13 14:36:24 -07005 "fmt"
Colin Cross92639f32017-12-11 14:39:41 -08006 "html/template"
7 "io/ioutil"
Colin Cross4572edd2015-05-13 14:36:24 -07008 "path/filepath"
Jaewoong Jung781f6b22019-02-06 16:20:17 -08009 "reflect"
Colin Cross4572edd2015-05-13 14:36:24 -070010
11 "github.com/google/blueprint"
12 "github.com/google/blueprint/bootstrap/bpdoc"
13 "github.com/google/blueprint/pathtools"
14)
15
Colin Cross92639f32017-12-11 14:39:41 -080016// ModuleTypeDocs returns a list of bpdoc.ModuleType objects that contain information relevant
17// to generating documentation for module types supported by the primary builder.
Lukacs T. Berki53537442021-03-12 08:31:19 +010018func ModuleTypeDocs(ctx *blueprint.Context, config interface{}, factories map[string]reflect.Value) ([]*bpdoc.Package, error) {
Colin Cross4572edd2015-05-13 14:36:24 -070019 // Find the module that's marked as the "primary builder", which means it's
20 // creating the binary that we'll use to generate the non-bootstrap
21 // build.ninja file.
22 var primaryBuilders []*goBinary
23 var minibp *goBinary
24 ctx.VisitAllModulesIf(isBootstrapBinaryModule,
25 func(module blueprint.Module) {
26 binaryModule := module.(*goBinary)
27 if binaryModule.properties.PrimaryBuilder {
28 primaryBuilders = append(primaryBuilders, binaryModule)
29 }
30 if ctx.ModuleName(binaryModule) == "minibp" {
31 minibp = binaryModule
32 }
33 })
34
35 if minibp == nil {
36 panic("missing minibp")
37 }
38
39 var primaryBuilder *goBinary
40 switch len(primaryBuilders) {
41 case 0:
42 // If there's no primary builder module then that means we'll use minibp
43 // as the primary builder.
44 primaryBuilder = minibp
45
46 case 1:
47 primaryBuilder = primaryBuilders[0]
48
49 default:
Colin Cross92639f32017-12-11 14:39:41 -080050 return nil, fmt.Errorf("multiple primary builder modules present")
Colin Cross4572edd2015-05-13 14:36:24 -070051 }
52
53 pkgFiles := make(map[string][]string)
54 ctx.VisitDepsDepthFirst(primaryBuilder, func(module blueprint.Module) {
55 switch m := module.(type) {
56 case (*goPackage):
57 pkgFiles[m.properties.PkgPath] = pathtools.PrefixPaths(m.properties.Srcs,
Lukacs T. Berki53537442021-03-12 08:31:19 +010058 filepath.Join(config.(BootstrapConfig).SrcDir(), ctx.ModuleDir(m)))
Colin Cross4572edd2015-05-13 14:36:24 -070059 default:
60 panic(fmt.Errorf("unknown dependency type %T", module))
61 }
62 })
63
Jaewoong Jung781f6b22019-02-06 16:20:17 -080064 mergedFactories := make(map[string]reflect.Value)
65 for moduleType, factory := range factories {
66 mergedFactories[moduleType] = factory
67 }
68
69 for moduleType, factory := range ctx.ModuleTypeFactories() {
70 if _, exists := mergedFactories[moduleType]; !exists {
71 mergedFactories[moduleType] = reflect.ValueOf(factory)
72 }
73 }
74
75 return bpdoc.AllPackages(pkgFiles, mergedFactories, ctx.ModuleTypePropertyStructs())
Colin Cross4572edd2015-05-13 14:36:24 -070076}
Colin Cross92639f32017-12-11 14:39:41 -080077
Lukacs T. Berki53537442021-03-12 08:31:19 +010078func writeDocs(ctx *blueprint.Context, config interface{}, filename string) error {
79 moduleTypeList, err := ModuleTypeDocs(ctx, config, nil)
Colin Cross92639f32017-12-11 14:39:41 -080080 if err != nil {
81 return err
82 }
83
84 buf := &bytes.Buffer{}
85
86 unique := 0
87
88 tmpl, err := template.New("file").Funcs(map[string]interface{}{
89 "unique": func() int {
90 unique++
91 return unique
92 }}).Parse(fileTemplate)
93 if err != nil {
94 return err
95 }
96
97 err = tmpl.Execute(buf, moduleTypeList)
98 if err != nil {
99 return err
100 }
101
102 err = ioutil.WriteFile(filename, buf.Bytes(), 0666)
103 if err != nil {
104 return err
105 }
106
107 return nil
108}
109
110const (
111 fileTemplate = `
112<html>
113<head>
114<title>Build Docs</title>
115<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
116<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
117<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
118</head>
119<body>
120<h1>Build Docs</h1>
121<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
122 {{range .}}
Jaewoong Jung781f6b22019-02-06 16:20:17 -0800123 <p>{{.Text}}</p>
124 {{range .ModuleTypes}}
125 {{ $collapseIndex := unique }}
126 <div class="panel panel-default">
127 <div class="panel-heading" role="tab" id="heading{{$collapseIndex}}">
128 <h2 class="panel-title">
129 <a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion" href="#collapse{{$collapseIndex}}" aria-expanded="false" aria-controls="collapse{{$collapseIndex}}">
130 {{.Name}}
131 </a>
132 </h2>
133 </div>
Colin Cross92639f32017-12-11 14:39:41 -0800134 </div>
Jaewoong Jung781f6b22019-02-06 16:20:17 -0800135 <div id="collapse{{$collapseIndex}}" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading{{$collapseIndex}}">
136 <div class="panel-body">
Colin Cross92639f32017-12-11 14:39:41 -0800137 <p>{{.Text}}</p>
Jaewoong Jung781f6b22019-02-06 16:20:17 -0800138 {{range .PropertyStructs}}
139 <p>{{.Text}}</p>
140 {{template "properties" .Properties}}
141 {{end}}
142 </div>
Colin Cross92639f32017-12-11 14:39:41 -0800143 </div>
Jaewoong Jung781f6b22019-02-06 16:20:17 -0800144 {{end}}
Colin Cross92639f32017-12-11 14:39:41 -0800145 {{end}}
146</div>
147</body>
148</html>
149
150{{define "properties"}}
151 <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
152 {{range .}}
153 {{$collapseIndex := unique}}
154 {{if .Properties}}
155 <div class="panel panel-default">
156 <div class="panel-heading" role="tab" id="heading{{$collapseIndex}}">
157 <h4 class="panel-title">
158 <a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion" href="#collapse{{$collapseIndex}}" aria-expanded="false" aria-controls="collapse{{$collapseIndex}}">
159 {{.Name}}{{range .OtherNames}}, {{.}}{{end}}
160 </a>
161 </h4>
162 </div>
163 </div>
164 <div id="collapse{{$collapseIndex}}" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading{{$collapseIndex}}">
165 <div class="panel-body">
166 <p>{{.Text}}</p>
167 {{range .OtherTexts}}<p>{{.}}</p>{{end}}
168 {{template "properties" .Properties}}
169 </div>
170 </div>
171 {{else}}
172 <div>
173 <h4>{{.Name}}{{range .OtherNames}}, {{.}}{{end}}</h4>
174 <p>{{.Text}}</p>
175 {{range .OtherTexts}}<p>{{.}}</p>{{end}}
176 <p><i>Type: {{.Type}}</i></p>
177 {{if .Default}}<p><i>Default: {{.Default}}</i></p>{{end}}
178 </div>
179 {{end}}
180 {{end}}
181 </div>
182{{end}}
183`
184)