diff --git a/Android.bp b/Android.bp index 643e8df37..ebf103800 100644 --- a/Android.bp +++ b/Android.bp @@ -61,6 +61,7 @@ bootstrap_go_package { "android/testing.go", "android/util.go", "android/variable.go", + "android/writedocs.go", // Lock down environment access last "android/env.go", diff --git a/android/config.go b/android/config.go index 0eebb5fbd..16870f10b 100644 --- a/android/config.go +++ b/android/config.go @@ -25,6 +25,7 @@ import ( "strings" "sync" + "github.com/google/blueprint/bootstrap" "github.com/google/blueprint/proptools" ) @@ -67,6 +68,7 @@ type config struct { FileConfigurableOptions ProductVariables productVariables + PrimaryBuilder string ConfigFileName string ProductVariablesFileName string @@ -91,6 +93,8 @@ type config struct { useOpenJDK9 bool // Use OpenJDK9, but possibly target 1.8 targetOpenJDK9 bool // Use OpenJDK9 and target 1.9 + stopBefore bootstrap.StopBefore + OncePer } @@ -312,14 +316,22 @@ func (c *config) fromEnv() error { return nil } -func (c *config) RemoveAbandonedFiles() bool { - return false +func (c *config) StopBefore() bootstrap.StopBefore { + return c.stopBefore } +func (c *config) SetStopBefore(stopBefore bootstrap.StopBefore) { + c.stopBefore = stopBefore +} + +var _ bootstrap.ConfigStopBefore = (*config)(nil) + func (c *config) BlueprintToolLocation() string { return filepath.Join(c.buildDir, "host", c.PrebuiltOS(), "bin") } +var _ bootstrap.ConfigBlueprintToolLocation = (*config)(nil) + // HostSystemTool looks for non-hermetic tools from the system we're running on. // Generally shouldn't be used, but useful to find the XCode SDK, etc. func (c *config) HostSystemTool(name string) string { diff --git a/android/writedocs.go b/android/writedocs.go new file mode 100644 index 000000000..9737030e0 --- /dev/null +++ b/android/writedocs.go @@ -0,0 +1,73 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android + +import ( + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/google/blueprint" +) + +func init() { + RegisterSingletonType("writedocs", DocsSingleton) +} + +func DocsSingleton() Singleton { + return &docsSingleton{} +} + +type docsSingleton struct{} + +func primaryBuilderPath(ctx SingletonContext) Path { + primaryBuilder, err := filepath.Rel(ctx.Config().BuildDir(), os.Args[0]) + if err != nil { + ctx.Errorf("path to primary builder %q is not in build dir %q", + os.Args[0], ctx.Config().BuildDir()) + } + + return PathForOutput(ctx, primaryBuilder) +} + +func (c *docsSingleton) GenerateBuildActions(ctx SingletonContext) { + // Generate build system docs for the primary builder. Generating docs reads the source + // files used to build the primary builder, but that dependency will be picked up through + // the dependency on the primary builder itself. There are no dependencies on the + // Blueprints files, as any relevant changes to the Blueprints files would have caused + // a rebuild of the primary builder. + docsFile := PathForOutput(ctx, "docs", "soong_build.html") + primaryBuilder := primaryBuilderPath(ctx) + soongDocs := ctx.Rule(pctx, "soongDocs", + blueprint.RuleParams{ + Command: fmt.Sprintf("%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()), + }) + + ctx.Build(pctx, BuildParams{ + Rule: soongDocs, + Output: docsFile, + }) + + // Add a phony target for building the documentation + ctx.Build(pctx, BuildParams{ + Rule: blueprint.Phony, + Output: PathForPhony(ctx, "soong_docs"), + Input: docsFile, + }) +} diff --git a/cmd/soong_build/Android.bp b/cmd/soong_build/Android.bp index d9daafc45..2536a535f 100644 --- a/cmd/soong_build/Android.bp +++ b/cmd/soong_build/Android.bp @@ -23,6 +23,7 @@ bootstrap_go_binary { ], srcs: [ "main.go", + "writedocs.go", ], primaryBuilder: true, } diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go index ddde1c595..40beab8c3 100644 --- a/cmd/soong_build/main.go +++ b/cmd/soong_build/main.go @@ -25,6 +25,14 @@ import ( "android/soong/android" ) +var ( + docFile string +) + +func init() { + flag.StringVar(&docFile, "soong_docs", "", "build documentation file to output") +} + func newNameResolver(config android.Config) *android.NameResolver { namespacePathsToExport := make(map[string]bool) @@ -56,9 +64,17 @@ func main() { os.Exit(1) } + if docFile != "" { + configuration.SetStopBefore(bootstrap.StopBeforePrepareBuildActions) + } + ctx.SetNameInterface(newNameResolver(configuration)) ctx.SetAllowMissingDependencies(configuration.AllowMissingDependencies()) bootstrap.Main(ctx.Context, configuration, configuration.ConfigFileName, configuration.ProductVariablesFileName) + + if docFile != "" { + writeDocs(ctx, docFile) + } } diff --git a/cmd/soong_build/writedocs.go b/cmd/soong_build/writedocs.go new file mode 100644 index 000000000..a6686c0db --- /dev/null +++ b/cmd/soong_build/writedocs.go @@ -0,0 +1,129 @@ +// Copyright 2017 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "android/soong/android" + "bytes" + "html/template" + "io/ioutil" + + "github.com/google/blueprint/bootstrap" +) + +func writeDocs(ctx *android.Context, filename string) error { + moduleTypeList, err := bootstrap.ModuleTypeDocs(ctx.Context) + 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 .}} + {{ $collapseIndex := unique }} +
+ +
+
+
+

{{.Text}}

+ {{range .PropertyStructs}} +

{{.Text}}

+ {{template "properties" .Properties}} + {{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}} +` +)