Refactor java/droiddoc.go in Soong.

The GenerateAndroidBuildActions() is too big to be maintained and added-in new
features.

Since the GenerateAndroidBuildActions() is a giant code block having build flags
setting and workflow logic mixed in it. So seperate these two main
stuff to only keep workflow logic in the function, and create other
indipendent flags setting functions to increase the modularity.

Test: m -j api-stubs-docs && m -j metalava-api-stubs-docs, and check
build.ninja file
Bug: b/70351683

Change-Id: I4230d353756aeb4b24640f641b8f8bab6b21204d
This commit is contained in:
Nan Zhang 2018-08-01 12:48:00 -07:00
parent a5949691b5
commit a40da04a99
1 changed files with 378 additions and 338 deletions

View File

@ -169,7 +169,7 @@ type DroiddocProperties struct {
// directory relative to top of the source tree that contains doc templates files.
Custom_template *string
// directories relative to top of the source tree which contains html/jd files.
// directories under current module source which contains html/jd files.
Html_dirs []string
// set a value in the Clearsilver hdf namespace.
@ -266,6 +266,34 @@ type DroiddocProperties struct {
Metalava_merge_annotations_dirs []string
}
//
// Common flags passed down to build rule
//
type droiddocBuilderFlags struct {
args string
bootClasspathArgs string
classpathArgs string
aidlFlags string
doclavaDocsFlags string
doclavaStubsFlags string
postDoclavaCmds string
metalavaAnnotationsFlags string
metalavaDocsFlags string
metalavaStubsFlags string
dokkaFlags string
}
func InitDroiddocModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
android.InitAndroidArchModule(module, hod, android.MultilibCommon)
android.InitDefaultableModule(module)
}
//
// Javadoc
//
type Javadoc struct {
android.ModuleBase
android.DefaultableModuleBase
@ -284,39 +312,6 @@ func (j *Javadoc) Srcs() android.Paths {
return android.Paths{j.stubsSrcJar}
}
var _ android.SourceFileProducer = (*Javadoc)(nil)
type Droiddoc struct {
Javadoc
properties DroiddocProperties
apiFile android.WritablePath
dexApiFile android.WritablePath
privateApiFile android.WritablePath
privateDexApiFile android.WritablePath
removedApiFile android.WritablePath
removedDexApiFile android.WritablePath
exactApiFile android.WritablePath
apiMappingFile android.WritablePath
checkCurrentApiTimestamp android.WritablePath
updateCurrentApiTimestamp android.WritablePath
checkLastReleasedApiTimestamp android.WritablePath
annotationsZip android.WritablePath
apiFilePath android.Path
}
type ApiFilePath interface {
ApiFilePath() android.Path
}
func InitDroiddocModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
android.InitAndroidArchModule(module, hod, android.MultilibCommon)
android.InitDefaultableModule(module)
}
func JavadocFactory() android.Module {
module := &Javadoc{}
@ -335,25 +330,7 @@ func JavadocHostFactory() android.Module {
return module
}
func DroiddocFactory() android.Module {
module := &Droiddoc{}
module.AddProperties(&module.properties,
&module.Javadoc.properties)
InitDroiddocModule(module, android.HostAndDeviceSupported)
return module
}
func DroiddocHostFactory() android.Module {
module := &Droiddoc{}
module.AddProperties(&module.properties,
&module.Javadoc.properties)
InitDroiddocModule(module, android.HostSupported)
return module
}
var _ android.SourceFileProducer = (*Javadoc)(nil)
func (j *Javadoc) sdkVersion() string {
return String(j.properties.Sdk_version)
@ -406,8 +383,8 @@ func (j *Javadoc) genWhitelistPathPrefixes(whitelistPathPrefixes map[string]bool
}
}
func (j *Javadoc) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaBuilderFlags {
var flags javaBuilderFlags
func (j *Javadoc) collectAidlFlags(ctx android.ModuleContext, deps deps) droiddocBuilderFlags {
var flags droiddocBuilderFlags
// aidl flags.
aidlFlags := j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs)
@ -443,7 +420,7 @@ func (j *Javadoc) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.Op
}
func (j *Javadoc) genSources(ctx android.ModuleContext, srcFiles android.Paths,
flags javaBuilderFlags) android.Paths {
flags droiddocBuilderFlags) android.Paths {
outSrcFiles := make(android.Paths, 0, len(srcFiles))
@ -536,7 +513,7 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps {
// do not pass exclude_srcs directly when expanding srcFiles since exclude_srcs
// may contain filegroup or genrule.
srcFiles := ctx.ExpandSources(j.properties.Srcs, j.properties.Exclude_srcs)
flags := j.collectBuilderFlags(ctx, deps)
flags := j.collectAidlFlags(ctx, deps)
srcFiles = j.genSources(ctx, srcFiles, flags)
// srcs may depend on some genrule output.
@ -608,6 +585,59 @@ func (j *Javadoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
})
}
//
// Droiddoc
//
type Droiddoc struct {
Javadoc
properties DroiddocProperties
apiFile android.WritablePath
dexApiFile android.WritablePath
privateApiFile android.WritablePath
privateDexApiFile android.WritablePath
removedApiFile android.WritablePath
removedDexApiFile android.WritablePath
exactApiFile android.WritablePath
apiMappingFile android.WritablePath
checkCurrentApiTimestamp android.WritablePath
updateCurrentApiTimestamp android.WritablePath
checkLastReleasedApiTimestamp android.WritablePath
annotationsZip android.WritablePath
apiFilePath android.Path
}
type ApiFilePath interface {
ApiFilePath() android.Path
}
func DroiddocFactory() android.Module {
module := &Droiddoc{}
module.AddProperties(&module.properties,
&module.Javadoc.properties)
InitDroiddocModule(module, android.HostAndDeviceSupported)
return module
}
func DroiddocHostFactory() android.Module {
module := &Droiddoc{}
module.AddProperties(&module.properties,
&module.Javadoc.properties)
InitDroiddocModule(module, android.HostSupported)
return module
}
func (d *Droiddoc) ApiFilePath() android.Path {
return d.apiFilePath
}
func (d *Droiddoc) checkCurrentApi() bool {
if String(d.properties.Check_api.Current.Api_file) != "" &&
String(d.properties.Check_api.Current.Removed_api_file) != "" {
@ -641,7 +671,7 @@ func (d *Droiddoc) DepsMutator(ctx android.BottomUpMutatorContext) {
ctx.AddDependency(ctx.Module(), droiddocTemplateTag, String(d.properties.Custom_template))
}
// extra_arg_files may contains filegroup or genrule.
// arg_files may contains filegroup or genrule.
android.ExtractSourcesDeps(ctx, d.properties.Arg_files)
// knowntags may contain filegroup or genrule.
@ -670,34 +700,25 @@ func (d *Droiddoc) DepsMutator(ctx android.BottomUpMutatorContext) {
}
}
func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
deps := d.Javadoc.collectDeps(ctx)
func (d *Droiddoc) initBuilderFlags(ctx android.ModuleContext, implicits *android.Paths, deps deps) (droiddocBuilderFlags, error) {
var flags droiddocBuilderFlags
var implicits android.Paths
implicits = append(implicits, deps.bootClasspath...)
implicits = append(implicits, deps.classpath...)
*implicits = append(*implicits, deps.bootClasspath...)
*implicits = append(*implicits, deps.classpath...)
var bootClasspathArgs string
javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), sdkContext(d))
// Doclava has problem with "-source 1.9", so override javaVersion when Doclava
// is running with EXPERIMENTAL_USE_OPENJDK9=true. And eventually Doclava will be
// replaced by Metalava.
if !Bool(d.properties.Metalava_enabled) {
javaVersion = "1.8"
}
// continue to use -bootclasspath even if Metalava under -source 1.9 is enabled
// since it doesn't support system modules yet.
if len(deps.bootClasspath.Strings()) > 0 {
// For OpenJDK 8 we can use -bootclasspath to define the core libraries code.
bootClasspathArgs = deps.bootClasspath.FormJavaClassPath("-bootclasspath")
flags.bootClasspathArgs = deps.bootClasspath.FormJavaClassPath("-bootclasspath")
}
classpathArgs := deps.classpath.FormJavaClassPath("-classpath")
flags.classpathArgs = deps.classpath.FormJavaClassPath("-classpath")
argFiles := ctx.ExpandSources(d.properties.Arg_files, nil)
argFilesMap := map[string]android.Path{}
for _, f := range argFiles {
implicits = append(implicits, f)
*implicits = append(*implicits, f)
if _, exists := argFilesMap[f.Rel()]; !exists {
argFilesMap[f.Rel()] = f
} else {
@ -706,7 +727,8 @@ func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
}
args, err := android.Expand(String(d.properties.Args), func(name string) (string, error) {
var err error
flags.args, err = android.Expand(String(d.properties.Args), func(name string) (string, error) {
if strings.HasPrefix(name, "location ") {
label := strings.TrimSpace(strings.TrimPrefix(name, "location "))
if f, ok := argFilesMap[label]; ok {
@ -722,163 +744,16 @@ func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if err != nil {
ctx.PropertyErrorf("args", "%s", err.Error())
return
return droiddocBuilderFlags{}, err
}
return flags, nil
}
genDocsForMetalava := false
var metalavaArgs string
if Bool(d.properties.Metalava_enabled) {
if strings.Contains(args, "--generate-documentation") {
if !strings.Contains(args, "-nodocs") {
genDocsForMetalava = true
}
// TODO(nanzhang): Add a Soong property to handle documentation args.
metalavaArgs = strings.Split(args, "--generate-documentation")[0]
} else {
metalavaArgs = args
}
}
func (d *Droiddoc) collectDoclavaDocsFlags(ctx android.ModuleContext, implicits *android.Paths,
javaVersion string, jsilver, doclava android.Path) string {
var templateDir, htmlDirArgs, htmlDir2Args string
if !Bool(d.properties.Metalava_enabled) || genDocsForMetalava {
if String(d.properties.Custom_template) == "" {
// TODO: This is almost always droiddoc-templates-sdk
ctx.PropertyErrorf("custom_template", "must specify a template")
}
ctx.VisitDirectDepsWithTag(droiddocTemplateTag, func(m android.Module) {
if t, ok := m.(*DroiddocTemplate); ok {
implicits = append(implicits, t.deps...)
templateDir = t.dir.String()
} else {
ctx.PropertyErrorf("custom_template", "module %q is not a droiddoc_template", ctx.OtherModuleName(m))
}
})
if len(d.properties.Html_dirs) > 0 {
htmlDir := android.PathForModuleSrc(ctx, d.properties.Html_dirs[0])
implicits = append(implicits, ctx.Glob(htmlDir.Join(ctx, "**/*").String(), nil)...)
htmlDirArgs = "-htmldir " + htmlDir.String()
}
if len(d.properties.Html_dirs) > 1 {
htmlDir2 := android.PathForModuleSrc(ctx, d.properties.Html_dirs[1])
implicits = append(implicits, ctx.Glob(htmlDir2.Join(ctx, "**/*").String(), nil)...)
htmlDir2Args = "-htmldir2 " + htmlDir2.String()
}
if len(d.properties.Html_dirs) > 2 {
ctx.PropertyErrorf("html_dirs", "Droiddoc only supports up to 2 html dirs")
}
knownTags := ctx.ExpandSources(d.properties.Knowntags, nil)
implicits = append(implicits, knownTags...)
for _, kt := range knownTags {
args = args + " -knowntags " + kt.String()
}
for _, hdf := range d.properties.Hdf {
args = args + " -hdf " + hdf
}
if String(d.properties.Proofread_file) != "" {
proofreadFile := android.PathForModuleOut(ctx, String(d.properties.Proofread_file))
args = args + " -proofread " + proofreadFile.String()
}
if String(d.properties.Todo_file) != "" {
// tricky part:
// we should not compute full path for todo_file through PathForModuleOut().
// the non-standard doclet will get the full path relative to "-o".
args = args + " -todo " + String(d.properties.Todo_file)
}
if String(d.properties.Resourcesdir) != "" {
// TODO: should we add files under resourcesDir to the implicits? It seems that
// resourcesDir is one sub dir of htmlDir
resourcesDir := android.PathForModuleSrc(ctx, String(d.properties.Resourcesdir))
args = args + " -resourcesdir " + resourcesDir.String()
}
if String(d.properties.Resourcesoutdir) != "" {
// TODO: it seems -resourceoutdir reference/android/images/ didn't get generated anywhere.
args = args + " -resourcesoutdir " + String(d.properties.Resourcesoutdir)
}
}
var docArgsForMetalava string
if Bool(d.properties.Metalava_enabled) && genDocsForMetalava {
docArgsForMetalava = strings.Split(args, "--generate-documentation")[1]
}
var implicitOutputs android.WritablePaths
if d.checkCurrentApi() || d.checkLastReleasedApi() || String(d.properties.Api_filename) != "" {
d.apiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_api.txt")
args = args + " -api " + d.apiFile.String()
metalavaArgs = metalavaArgs + " --api " + d.apiFile.String()
implicitOutputs = append(implicitOutputs, d.apiFile)
d.apiFilePath = d.apiFile
}
if d.checkCurrentApi() || d.checkLastReleasedApi() || String(d.properties.Removed_api_filename) != "" {
d.removedApiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_removed.txt")
args = args + " -removedApi " + d.removedApiFile.String()
metalavaArgs = metalavaArgs + " --removed-api " + d.removedApiFile.String()
implicitOutputs = append(implicitOutputs, d.removedApiFile)
}
if String(d.properties.Private_api_filename) != "" {
d.privateApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_api_filename))
args = args + " -privateApi " + d.privateApiFile.String()
metalavaArgs = metalavaArgs + " --private-api " + d.privateApiFile.String()
implicitOutputs = append(implicitOutputs, d.privateApiFile)
}
if String(d.properties.Dex_api_filename) != "" {
d.dexApiFile = android.PathForModuleOut(ctx, String(d.properties.Dex_api_filename))
args = args + " -dexApi " + d.dexApiFile.String()
implicitOutputs = append(implicitOutputs, d.dexApiFile)
}
if String(d.properties.Private_dex_api_filename) != "" {
d.privateDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_dex_api_filename))
args = args + " -privateDexApi " + d.privateDexApiFile.String()
metalavaArgs = metalavaArgs + " --private-dex-api " + d.privateDexApiFile.String()
implicitOutputs = append(implicitOutputs, d.privateDexApiFile)
}
if String(d.properties.Removed_dex_api_filename) != "" {
d.removedDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Removed_dex_api_filename))
args = args + " -removedDexApi " + d.removedDexApiFile.String()
metalavaArgs = metalavaArgs + " --removed-dex-api " + d.removedDexApiFile.String()
implicitOutputs = append(implicitOutputs, d.removedDexApiFile)
}
if String(d.properties.Exact_api_filename) != "" {
d.exactApiFile = android.PathForModuleOut(ctx, String(d.properties.Exact_api_filename))
args = args + " -exactApi " + d.exactApiFile.String()
metalavaArgs = metalavaArgs + " --exact-api " + d.exactApiFile.String()
implicitOutputs = append(implicitOutputs, d.exactApiFile)
}
if String(d.properties.Dex_mapping_filename) != "" {
d.apiMappingFile = android.PathForModuleOut(ctx, String(d.properties.Dex_mapping_filename))
args = args + " -apiMapping " + d.apiMappingFile.String()
// Omitted: metalava support
implicitOutputs = append(implicitOutputs, d.apiMappingFile)
}
implicits = append(implicits, d.Javadoc.srcJars...)
implicitOutputs = append(implicitOutputs, d.Javadoc.docZip)
for _, o := range d.properties.Out {
implicitOutputs = append(implicitOutputs, android.PathForModuleGen(ctx, o))
}
jsilver := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "jsilver.jar")
doclava := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "doclava.jar")
*implicits = append(*implicits, jsilver)
*implicits = append(*implicits, doclava)
var date string
if runtime.GOOS == "darwin" {
@ -887,43 +762,280 @@ func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
date = `date -d`
}
doclavaOpts := "-source " + javaVersion + " -J-Xmx1600m -J-XX:-OmitStackTraceInFastThrow -XDignore.symbol.file " +
args := " -source " + javaVersion + " -J-Xmx1600m -J-XX:-OmitStackTraceInFastThrow -XDignore.symbol.file " +
"-doclet com.google.doclava.Doclava -docletpath " + jsilver.String() + ":" + doclava.String() + " " +
"-templatedir " + templateDir + " " + htmlDirArgs + " " + htmlDir2Args + " " +
"-hdf page.build " + ctx.Config().BuildId() + "-" + ctx.Config().BuildNumberFromFile() + " " +
`-hdf page.now "$$(` + date + ` @$$(cat ` + ctx.Config().Getenv("BUILD_DATETIME_FILE") + `) "+%d %b %Y %k:%M")" `
if String(d.properties.Custom_template) == "" {
// TODO: This is almost always droiddoc-templates-sdk
ctx.PropertyErrorf("custom_template", "must specify a template")
}
ctx.VisitDirectDepsWithTag(droiddocTemplateTag, func(m android.Module) {
if t, ok := m.(*DroiddocTemplate); ok {
*implicits = append(*implicits, t.deps...)
args = args + " -templatedir " + t.dir.String()
} else {
ctx.PropertyErrorf("custom_template", "module %q is not a droiddoc_template", ctx.OtherModuleName(m))
}
})
if len(d.properties.Html_dirs) > 0 {
htmlDir := android.PathForModuleSrc(ctx, d.properties.Html_dirs[0])
*implicits = append(*implicits, ctx.Glob(htmlDir.Join(ctx, "**/*").String(), nil)...)
args = args + " -htmldir " + htmlDir.String()
}
if len(d.properties.Html_dirs) > 1 {
htmlDir2 := android.PathForModuleSrc(ctx, d.properties.Html_dirs[1])
*implicits = append(*implicits, ctx.Glob(htmlDir2.Join(ctx, "**/*").String(), nil)...)
args = args + " -htmldir2 " + htmlDir2.String()
}
if len(d.properties.Html_dirs) > 2 {
ctx.PropertyErrorf("html_dirs", "Droiddoc only supports up to 2 html dirs")
}
knownTags := ctx.ExpandSources(d.properties.Knowntags, nil)
*implicits = append(*implicits, knownTags...)
for _, kt := range knownTags {
args = args + " -knowntags " + kt.String()
}
for _, hdf := range d.properties.Hdf {
args = args + " -hdf " + hdf
}
if String(d.properties.Proofread_file) != "" {
proofreadFile := android.PathForModuleOut(ctx, String(d.properties.Proofread_file))
args = args + " -proofread " + proofreadFile.String()
}
if String(d.properties.Todo_file) != "" {
// tricky part:
// we should not compute full path for todo_file through PathForModuleOut().
// the non-standard doclet will get the full path relative to "-o".
args = args + " -todo " + String(d.properties.Todo_file)
}
if String(d.properties.Resourcesdir) != "" {
// TODO: should we add files under resourcesDir to the implicits? It seems that
// resourcesDir is one sub dir of htmlDir
resourcesDir := android.PathForModuleSrc(ctx, String(d.properties.Resourcesdir))
args = args + " -resourcesdir " + resourcesDir.String()
}
if String(d.properties.Resourcesoutdir) != "" {
// TODO: it seems -resourceoutdir reference/android/images/ didn't get generated anywhere.
args = args + " -resourcesoutdir " + String(d.properties.Resourcesoutdir)
}
return args
}
func (d *Droiddoc) collectStubsFlags(ctx android.ModuleContext, implicitOutputs *android.WritablePaths) (string, string) {
var doclavaFlags, MetalavaFlags string
if d.checkCurrentApi() || d.checkLastReleasedApi() || String(d.properties.Api_filename) != "" {
d.apiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_api.txt")
doclavaFlags += " -api " + d.apiFile.String()
MetalavaFlags = MetalavaFlags + " --api " + d.apiFile.String()
*implicitOutputs = append(*implicitOutputs, d.apiFile)
d.apiFilePath = d.apiFile
}
if d.checkCurrentApi() || d.checkLastReleasedApi() || String(d.properties.Removed_api_filename) != "" {
d.removedApiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_removed.txt")
doclavaFlags += " -removedApi " + d.removedApiFile.String()
MetalavaFlags = MetalavaFlags + " --removed-api " + d.removedApiFile.String()
*implicitOutputs = append(*implicitOutputs, d.removedApiFile)
}
if String(d.properties.Private_api_filename) != "" {
d.privateApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_api_filename))
doclavaFlags += " -privateApi " + d.privateApiFile.String()
MetalavaFlags = MetalavaFlags + " --private-api " + d.privateApiFile.String()
*implicitOutputs = append(*implicitOutputs, d.privateApiFile)
}
if String(d.properties.Dex_api_filename) != "" {
d.dexApiFile = android.PathForModuleOut(ctx, String(d.properties.Dex_api_filename))
doclavaFlags += " -dexApi " + d.dexApiFile.String()
*implicitOutputs = append(*implicitOutputs, d.dexApiFile)
}
if String(d.properties.Private_dex_api_filename) != "" {
d.privateDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_dex_api_filename))
doclavaFlags += " -privateDexApi " + d.privateDexApiFile.String()
MetalavaFlags = MetalavaFlags + " --private-dex-api " + d.privateDexApiFile.String()
*implicitOutputs = append(*implicitOutputs, d.privateDexApiFile)
}
if String(d.properties.Removed_dex_api_filename) != "" {
d.removedDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Removed_dex_api_filename))
doclavaFlags += " -removedDexApi " + d.removedDexApiFile.String()
MetalavaFlags = MetalavaFlags + " --removed-dex-api " + d.removedDexApiFile.String()
*implicitOutputs = append(*implicitOutputs, d.removedDexApiFile)
}
if String(d.properties.Exact_api_filename) != "" {
d.exactApiFile = android.PathForModuleOut(ctx, String(d.properties.Exact_api_filename))
doclavaFlags += " -exactApi " + d.exactApiFile.String()
MetalavaFlags = MetalavaFlags + " --exact-api " + d.exactApiFile.String()
*implicitOutputs = append(*implicitOutputs, d.exactApiFile)
}
if String(d.properties.Dex_mapping_filename) != "" {
d.apiMappingFile = android.PathForModuleOut(ctx, String(d.properties.Dex_mapping_filename))
doclavaFlags += " -apiMapping " + d.apiMappingFile.String()
// Omitted: metalava support
*implicitOutputs = append(*implicitOutputs, d.apiMappingFile)
}
if BoolDefault(d.properties.Create_stubs, true) {
doclavaFlags += " -stubs " + android.PathForModuleOut(ctx, "docs", "stubsDir").String()
}
if Bool(d.properties.Write_sdk_values) {
doclavaFlags += " -sdkvalues " + android.PathForModuleOut(ctx, "docs", "out").String()
}
return doclavaFlags, MetalavaFlags
}
func (d *Droiddoc) getPostDoclavaCmds(ctx android.ModuleContext, implicits *android.Paths) string {
var cmds string
if String(d.properties.Static_doc_index_redirect) != "" {
static_doc_index_redirect := ctx.ExpandSource(String(d.properties.Static_doc_index_redirect),
"static_doc_index_redirect")
*implicits = append(*implicits, static_doc_index_redirect)
cmds = cmds + " && cp " + static_doc_index_redirect.String() + " " +
android.PathForModuleOut(ctx, "docs", "out", "index.html").String()
}
if String(d.properties.Static_doc_properties) != "" {
static_doc_properties := ctx.ExpandSource(String(d.properties.Static_doc_properties),
"static_doc_properties")
*implicits = append(*implicits, static_doc_properties)
cmds = cmds + " && cp " + static_doc_properties.String() + " " +
android.PathForModuleOut(ctx, "docs", "out", "source.properties").String()
}
return cmds
}
func (d *Droiddoc) collectMetalavaAnnotationsFlags(
ctx android.ModuleContext, implicits *android.Paths, implicitOutputs *android.WritablePaths) string {
var flags string
if String(d.properties.Metalava_previous_api) != "" {
previousApi := ctx.ExpandSource(String(d.properties.Metalava_previous_api),
"metalava_previous_api")
flags += " --previous-api " + previousApi.String()
*implicits = append(*implicits, previousApi)
}
if Bool(d.properties.Metalava_annotations_enabled) {
if String(d.properties.Metalava_previous_api) == "" {
ctx.PropertyErrorf("metalava_previous_api",
"has to be non-empty if annotations was enabled!")
}
flags += " --include-annotations --migrate-nullness"
d.annotationsZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"_annotations.zip")
*implicitOutputs = append(*implicitOutputs, d.annotationsZip)
if len(d.properties.Metalava_merge_annotations_dirs) == 0 {
ctx.PropertyErrorf("metalava_merge_annotations_dirs",
"has to be non-empty if annotations was enabled!")
}
mergeAnnotationsDirs := android.PathsForSource(ctx, d.properties.Metalava_merge_annotations_dirs)
flags += " --extract-annotations " + d.annotationsZip.String()
for _, mergeAnnotationsDir := range mergeAnnotationsDirs {
flags += " --merge-annotations " + mergeAnnotationsDir.String()
}
// TODO(tnorbye): find owners to fix these warnings when annotation was enabled.
flags += " --hide HiddenTypedefConstant --hide SuperfluousPrefix --hide AnnotationExtraction "
}
return flags
}
func (d *Droiddoc) collectMetalavaDocsFlags(ctx android.ModuleContext,
bootClasspathArgs, classpathArgs string) string {
return " --doc-stubs " + android.PathForModuleOut(ctx, "docs", "docStubsDir").String() +
" --write-doc-stubs-source-list $outDir/doc_stubs_src_list " +
" --generate-documentation ${config.JavadocCmd} -encoding UTF-8 DOC_STUBS_SOURCE_LIST " +
bootClasspathArgs + " " + classpathArgs + " " + " -sourcepath " +
android.PathForModuleOut(ctx, "docs", "docStubsDir").String() + " -quiet -d $outDir "
}
func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
deps := d.Javadoc.collectDeps(ctx)
javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), sdkContext(d))
// Doclava has problem with "-source 1.9", so override javaVersion when Doclava
// is running with EXPERIMENTAL_USE_OPENJDK9=true. And eventually Doclava will be
// replaced by Metalava.
if !Bool(d.properties.Metalava_enabled) {
opts := doclavaOpts + args
javaVersion = "1.8"
}
implicits = append(implicits, jsilver)
implicits = append(implicits, doclava)
jsilver := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "jsilver.jar")
doclava := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "doclava.jar")
java8Home := ctx.Config().Getenv("ANDROID_JAVA8_HOME")
checkApiClasspath := classpath{jsilver, doclava, android.PathForSource(ctx, java8Home, "lib/tools.jar")}
if BoolDefault(d.properties.Create_stubs, true) {
opts += " -stubs " + android.PathForModuleOut(ctx, "docs", "stubsDir").String()
var implicits android.Paths
implicits = append(implicits, d.Javadoc.srcJars...)
var implicitOutputs android.WritablePaths
implicitOutputs = append(implicitOutputs, d.Javadoc.docZip)
for _, o := range d.properties.Out {
implicitOutputs = append(implicitOutputs, android.PathForModuleGen(ctx, o))
}
flags, err := d.initBuilderFlags(ctx, &implicits, deps)
if err != nil {
return
}
flags.doclavaStubsFlags, flags.metalavaStubsFlags = d.collectStubsFlags(ctx, &implicitOutputs)
if Bool(d.properties.Metalava_enabled) {
opts := flags.metalavaStubsFlags
flags.metalavaAnnotationsFlags = d.collectMetalavaAnnotationsFlags(ctx, &implicits, &implicitOutputs)
opts += flags.metalavaAnnotationsFlags
if strings.Contains(flags.args, "--generate-documentation") {
// TODO(nanzhang): Add a Soong property to handle documentation args.
flags.doclavaDocsFlags = d.collectDoclavaDocsFlags(ctx, &implicits, javaVersion, jsilver, doclava)
flags.metalavaDocsFlags = d.collectMetalavaDocsFlags(ctx, flags.bootClasspathArgs, flags.classpathArgs)
opts += " " + strings.Split(flags.args, "--generate-documentation")[0] + " " +
flags.metalavaDocsFlags + flags.doclavaDocsFlags +
" " + strings.Split(flags.args, "--generate-documentation")[1]
} else {
opts += " " + flags.args
}
if Bool(d.properties.Write_sdk_values) {
opts += " -sdkvalues " + android.PathForModuleOut(ctx, "docs", "out").String()
}
var postDoclavaCmds string
if String(d.properties.Static_doc_index_redirect) != "" {
static_doc_index_redirect := ctx.ExpandSource(String(d.properties.Static_doc_index_redirect),
"static_doc_index_redirect")
implicits = append(implicits, static_doc_index_redirect)
postDoclavaCmds += " && cp " + static_doc_index_redirect.String() + " " +
android.PathForModuleOut(ctx, "docs", "out", "index.html").String()
}
if String(d.properties.Static_doc_properties) != "" {
static_doc_properties := ctx.ExpandSource(String(d.properties.Static_doc_properties),
"static_doc_properties")
implicits = append(implicits, static_doc_properties)
postDoclavaCmds += " && cp " + static_doc_properties.String() + " " +
android.PathForModuleOut(ctx, "docs", "out", "source.properties").String()
}
ctx.Build(pctx, android.BuildParams{
Rule: metalava,
Description: "Metalava",
Output: d.Javadoc.stubsSrcJar,
Inputs: d.Javadoc.srcFiles,
Implicits: implicits,
ImplicitOutputs: implicitOutputs,
Args: map[string]string{
"outDir": android.PathForModuleOut(ctx, "docs", "out").String(),
"srcJarDir": android.PathForModuleOut(ctx, "docs", "srcjars").String(),
"stubsDir": android.PathForModuleOut(ctx, "docs", "stubsDir").String(),
"srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "),
"javaVersion": javaVersion,
"bootclasspathArgs": flags.bootClasspathArgs,
"classpathArgs": flags.classpathArgs,
"sourcepath": strings.Join(d.Javadoc.sourcepaths.Strings(), ":"),
"docZip": d.Javadoc.docZip.String(),
"opts": opts,
},
})
} else {
flags.doclavaDocsFlags = d.collectDoclavaDocsFlags(ctx, &implicits, javaVersion, jsilver, doclava)
flags.postDoclavaCmds = d.getPostDoclavaCmds(ctx, &implicits)
ctx.Build(pctx, android.BuildParams{
Rule: javadoc,
Description: "Droiddoc",
@ -936,87 +1048,16 @@ func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
"srcJarDir": android.PathForModuleOut(ctx, "docs", "srcjars").String(),
"stubsDir": android.PathForModuleOut(ctx, "docs", "stubsDir").String(),
"srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "),
"opts": opts,
"bootclasspathArgs": bootClasspathArgs,
"classpathArgs": classpathArgs,
"opts": flags.doclavaDocsFlags + flags.doclavaStubsFlags + " " + flags.args,
"bootclasspathArgs": flags.bootClasspathArgs,
"classpathArgs": flags.classpathArgs,
"sourcepath": strings.Join(d.Javadoc.sourcepaths.Strings(), ":"),
"docZip": d.Javadoc.docZip.String(),
"postDoclavaCmds": postDoclavaCmds,
"postDoclavaCmds": flags.postDoclavaCmds,
},
})
} else {
opts := metalavaArgs
buildArgs := map[string]string{
"outDir": android.PathForModuleOut(ctx, "docs", "out").String(),
"srcJarDir": android.PathForModuleOut(ctx, "docs", "srcjars").String(),
"stubsDir": android.PathForModuleOut(ctx, "docs", "stubsDir").String(),
"srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "),
"javaVersion": javaVersion,
"bootclasspathArgs": bootClasspathArgs,
"classpathArgs": classpathArgs,
"sourcepath": strings.Join(d.Javadoc.sourcepaths.Strings(), ":"),
"docZip": d.Javadoc.docZip.String(),
}
var previousApi android.Path
if String(d.properties.Metalava_previous_api) != "" {
previousApi = ctx.ExpandSource(String(d.properties.Metalava_previous_api),
"metalava_previous_api")
opts += " --previous-api " + previousApi.String()
implicits = append(implicits, previousApi)
}
if Bool(d.properties.Metalava_annotations_enabled) {
if String(d.properties.Metalava_previous_api) == "" {
ctx.PropertyErrorf("metalava_previous_api",
"has to be non-empty if annotations was enabled!")
}
opts += " --include-annotations --migrate-nullness"
d.annotationsZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"_annotations.zip")
implicitOutputs = append(implicitOutputs, d.annotationsZip)
if len(d.properties.Metalava_merge_annotations_dirs) == 0 {
ctx.PropertyErrorf("metalava_merge_annotations_dirs",
"has to be non-empty if annotations was enabled!")
}
mergeAnnotationsDirs := android.PathsForSource(ctx, d.properties.Metalava_merge_annotations_dirs)
opts += " --extract-annotations " + d.annotationsZip.String()
for _, mergeAnnotationsDir := range mergeAnnotationsDirs {
opts += " --merge-annotations " + mergeAnnotationsDir.String()
}
// TODO(tnorbye): find owners to fix these warnings when annotation was enabled.
opts += " --hide HiddenTypedefConstant --hide SuperfluousPrefix --hide AnnotationExtraction"
}
if genDocsForMetalava {
opts += " --doc-stubs " + android.PathForModuleOut(ctx, "docs", "docStubsDir").String() +
" --write-doc-stubs-source-list $outDir/doc_stubs_src_list " +
" --generate-documentation ${config.JavadocCmd} -encoding UTF-8 DOC_STUBS_SOURCE_LIST " +
doclavaOpts + docArgsForMetalava + bootClasspathArgs + " " + classpathArgs + " " + " -sourcepath " +
android.PathForModuleOut(ctx, "docs", "docStubsDir").String() + " -quiet -d $outDir "
implicits = append(implicits, jsilver)
implicits = append(implicits, doclava)
}
buildArgs["opts"] = opts
ctx.Build(pctx, android.BuildParams{
Rule: metalava,
Description: "Metalava",
Output: d.Javadoc.stubsSrcJar,
Inputs: d.Javadoc.srcFiles,
Implicits: implicits,
ImplicitOutputs: implicitOutputs,
Args: buildArgs,
})
}
java8Home := ctx.Config().Getenv("ANDROID_JAVA8_HOME")
checkApiClasspath := classpath{jsilver, doclava, android.PathForSource(ctx, java8Home, "lib/tools.jar")}
if d.checkCurrentApi() && !ctx.Config().IsPdkBuild() {
d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, "check_current_api.timestamp")
@ -1053,7 +1094,6 @@ func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
})
d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, "update_current_api.timestamp")
ctx.Build(pctx, android.BuildParams{
Rule: updateApi,
Description: "update current API",
@ -1067,6 +1107,7 @@ func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
},
})
}
if d.checkLastReleasedApi() && !ctx.Config().IsPdkBuild() {
d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, "check_last_released_api.timestamp")
@ -1098,10 +1139,9 @@ func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
}
func (d *Droiddoc) ApiFilePath() android.Path {
return d.apiFilePath
}
//
// Droiddoc Template
//
var droiddocTemplateTag = dependencyTag{name: "droiddoc-template"}
type DroiddocTemplateProperties struct {