droiddoc.go 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913
  1. // Copyright 2018 Google Inc. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package java
  15. import (
  16. "fmt"
  17. "path/filepath"
  18. "strings"
  19. "github.com/google/blueprint/proptools"
  20. "android/soong/android"
  21. "android/soong/java/config"
  22. )
  23. func init() {
  24. RegisterDocsBuildComponents(android.InitRegistrationContext)
  25. }
  26. func RegisterDocsBuildComponents(ctx android.RegistrationContext) {
  27. ctx.RegisterModuleType("doc_defaults", DocDefaultsFactory)
  28. ctx.RegisterModuleType("droiddoc", DroiddocFactory)
  29. ctx.RegisterModuleType("droiddoc_host", DroiddocHostFactory)
  30. ctx.RegisterModuleType("droiddoc_exported_dir", ExportedDroiddocDirFactory)
  31. ctx.RegisterModuleType("javadoc", JavadocFactory)
  32. ctx.RegisterModuleType("javadoc_host", JavadocHostFactory)
  33. }
  34. type JavadocProperties struct {
  35. // list of source files used to compile the Java module. May be .java, .logtags, .proto,
  36. // or .aidl files.
  37. Srcs []string `android:"path,arch_variant"`
  38. // list of source files that should not be used to build the Java module.
  39. // This is most useful in the arch/multilib variants to remove non-common files
  40. // filegroup or genrule can be included within this property.
  41. Exclude_srcs []string `android:"path,arch_variant"`
  42. // list of package names that should actually be used. If this property is left unspecified,
  43. // all the sources from the srcs property is used.
  44. Filter_packages []string
  45. // list of java libraries that will be in the classpath.
  46. Libs []string `android:"arch_variant"`
  47. // If set to false, don't allow this module(-docs.zip) to be exported. Defaults to true.
  48. Installable *bool
  49. // if not blank, set to the version of the sdk to compile against.
  50. // Defaults to compiling against the current platform.
  51. Sdk_version *string `android:"arch_variant"`
  52. // When targeting 1.9 and above, override the modules to use with --system,
  53. // otherwise provides defaults libraries to add to the bootclasspath.
  54. // Defaults to "none"
  55. System_modules *string
  56. Aidl struct {
  57. // Top level directories to pass to aidl tool
  58. Include_dirs []string
  59. // Directories rooted at the Android.bp file to pass to aidl tool
  60. Local_include_dirs []string
  61. }
  62. // If not blank, set the java version passed to javadoc as -source
  63. Java_version *string
  64. // local files that are used within user customized droiddoc options.
  65. Arg_files []string `android:"path"`
  66. // user customized droiddoc args. Deprecated, use flags instead.
  67. // Available variables for substitution:
  68. //
  69. // $(location <label>): the path to the arg_files with name <label>
  70. // $$: a literal $
  71. Args *string
  72. // user customized droiddoc args. Not compatible with property args.
  73. // Available variables for substitution:
  74. //
  75. // $(location <label>): the path to the arg_files with name <label>
  76. // $$: a literal $
  77. Flags []string
  78. // names of the output files used in args that will be generated
  79. Out []string
  80. }
  81. type ApiToCheck struct {
  82. // path to the API txt file that the new API extracted from source code is checked
  83. // against. The path can be local to the module or from other module (via :module syntax).
  84. Api_file *string `android:"path"`
  85. // path to the API txt file that the new @removed API extractd from source code is
  86. // checked against. The path can be local to the module or from other module (via
  87. // :module syntax).
  88. Removed_api_file *string `android:"path"`
  89. // If not blank, path to the baseline txt file for approved API check violations.
  90. Baseline_file *string `android:"path"`
  91. // Arguments to the apicheck tool.
  92. Args *string
  93. }
  94. type DroiddocProperties struct {
  95. // directory relative to top of the source tree that contains doc templates files.
  96. Custom_template *string
  97. // directories under current module source which contains html/jd files.
  98. Html_dirs []string
  99. // set a value in the Clearsilver hdf namespace.
  100. Hdf []string
  101. // proofread file contains all of the text content of the javadocs concatenated into one file,
  102. // suitable for spell-checking and other goodness.
  103. Proofread_file *string
  104. // a todo file lists the program elements that are missing documentation.
  105. // At some point, this might be improved to show more warnings.
  106. Todo_file *string `android:"path"`
  107. // directory under current module source that provide additional resources (images).
  108. Resourcesdir *string
  109. // resources output directory under out/soong/.intermediates.
  110. Resourcesoutdir *string
  111. // index.html under current module will be copied to docs out dir, if not null.
  112. Static_doc_index_redirect *string `android:"path"`
  113. // source.properties under current module will be copied to docs out dir, if not null.
  114. Static_doc_properties *string `android:"path"`
  115. // a list of files under current module source dir which contains known tags in Java sources.
  116. // filegroup or genrule can be included within this property.
  117. Knowntags []string `android:"path"`
  118. // if set to true, generate docs through Dokka instead of Doclava.
  119. Dokka_enabled *bool
  120. // Compat config XML. Generates compat change documentation if set.
  121. Compat_config *string `android:"path"`
  122. }
  123. // Common flags passed down to build rule
  124. type droiddocBuilderFlags struct {
  125. bootClasspathArgs string
  126. classpathArgs string
  127. sourcepathArgs string
  128. dokkaClasspathArgs string
  129. aidlFlags string
  130. aidlDeps android.Paths
  131. doclavaStubsFlags string
  132. doclavaDocsFlags string
  133. postDoclavaCmds string
  134. }
  135. func InitDroiddocModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
  136. android.InitAndroidArchModule(module, hod, android.MultilibCommon)
  137. android.InitDefaultableModule(module)
  138. }
  139. func apiCheckEnabled(ctx android.ModuleContext, apiToCheck ApiToCheck, apiVersionTag string) bool {
  140. if ctx.Config().IsEnvTrue("WITHOUT_CHECK_API") {
  141. return false
  142. } else if String(apiToCheck.Api_file) != "" && String(apiToCheck.Removed_api_file) != "" {
  143. return true
  144. } else if String(apiToCheck.Api_file) != "" {
  145. panic("for " + apiVersionTag + " removed_api_file has to be non-empty!")
  146. } else if String(apiToCheck.Removed_api_file) != "" {
  147. panic("for " + apiVersionTag + " api_file has to be non-empty!")
  148. }
  149. return false
  150. }
  151. // Javadoc
  152. type Javadoc struct {
  153. android.ModuleBase
  154. android.DefaultableModuleBase
  155. properties JavadocProperties
  156. srcJars android.Paths
  157. srcFiles android.Paths
  158. sourcepaths android.Paths
  159. implicits android.Paths
  160. docZip android.WritablePath
  161. stubsSrcJar android.WritablePath
  162. }
  163. func (j *Javadoc) OutputFiles(tag string) (android.Paths, error) {
  164. switch tag {
  165. case "":
  166. return android.Paths{j.stubsSrcJar}, nil
  167. case ".docs.zip":
  168. return android.Paths{j.docZip}, nil
  169. default:
  170. return nil, fmt.Errorf("unsupported module reference tag %q", tag)
  171. }
  172. }
  173. // javadoc converts .java source files to documentation using javadoc.
  174. func JavadocFactory() android.Module {
  175. module := &Javadoc{}
  176. module.AddProperties(&module.properties)
  177. InitDroiddocModule(module, android.HostAndDeviceSupported)
  178. return module
  179. }
  180. // javadoc_host converts .java source files to documentation using javadoc.
  181. func JavadocHostFactory() android.Module {
  182. module := &Javadoc{}
  183. module.AddProperties(&module.properties)
  184. InitDroiddocModule(module, android.HostSupported)
  185. return module
  186. }
  187. var _ android.OutputFileProducer = (*Javadoc)(nil)
  188. func (j *Javadoc) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
  189. return android.SdkSpecFrom(ctx, String(j.properties.Sdk_version))
  190. }
  191. func (j *Javadoc) SystemModules() string {
  192. return proptools.String(j.properties.System_modules)
  193. }
  194. func (j *Javadoc) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
  195. return j.SdkVersion(ctx).ApiLevel
  196. }
  197. func (j *Javadoc) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel {
  198. return j.SdkVersion(ctx).ApiLevel
  199. }
  200. func (j *Javadoc) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
  201. return j.SdkVersion(ctx).ApiLevel
  202. }
  203. func (j *Javadoc) addDeps(ctx android.BottomUpMutatorContext) {
  204. if ctx.Device() {
  205. sdkDep := decodeSdkDep(ctx, android.SdkContext(j))
  206. if sdkDep.useModule {
  207. ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...)
  208. ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules)
  209. ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...)
  210. ctx.AddVariationDependencies(nil, sdkLibTag, sdkDep.classpath...)
  211. }
  212. }
  213. ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
  214. }
  215. func (j *Javadoc) collectAidlFlags(ctx android.ModuleContext, deps deps) droiddocBuilderFlags {
  216. var flags droiddocBuilderFlags
  217. flags.aidlFlags, flags.aidlDeps = j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs)
  218. return flags
  219. }
  220. func (j *Javadoc) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.OptionalPath,
  221. aidlIncludeDirs android.Paths) (string, android.Paths) {
  222. aidlIncludes := android.PathsForModuleSrc(ctx, j.properties.Aidl.Local_include_dirs)
  223. aidlIncludes = append(aidlIncludes, android.PathsForSource(ctx, j.properties.Aidl.Include_dirs)...)
  224. var flags []string
  225. var deps android.Paths
  226. if aidlPreprocess.Valid() {
  227. flags = append(flags, "-p"+aidlPreprocess.String())
  228. deps = append(deps, aidlPreprocess.Path())
  229. } else {
  230. flags = append(flags, android.JoinWithPrefix(aidlIncludeDirs.Strings(), "-I"))
  231. }
  232. flags = append(flags, android.JoinWithPrefix(aidlIncludes.Strings(), "-I"))
  233. flags = append(flags, "-I"+android.PathForModuleSrc(ctx).String())
  234. if src := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "src"); src.Valid() {
  235. flags = append(flags, "-I"+src.String())
  236. }
  237. minSdkVersion := j.MinSdkVersion(ctx).FinalOrFutureInt()
  238. flags = append(flags, fmt.Sprintf("--min_sdk_version=%v", minSdkVersion))
  239. return strings.Join(flags, " "), deps
  240. }
  241. // TODO: remove the duplication between this and the one in gen.go
  242. func (j *Javadoc) genSources(ctx android.ModuleContext, srcFiles android.Paths,
  243. flags droiddocBuilderFlags) android.Paths {
  244. outSrcFiles := make(android.Paths, 0, len(srcFiles))
  245. var aidlSrcs android.Paths
  246. aidlIncludeFlags := genAidlIncludeFlags(ctx, srcFiles, android.Paths{})
  247. for _, srcFile := range srcFiles {
  248. switch srcFile.Ext() {
  249. case ".aidl":
  250. aidlSrcs = append(aidlSrcs, srcFile)
  251. case ".logtags":
  252. javaFile := genLogtags(ctx, srcFile)
  253. outSrcFiles = append(outSrcFiles, javaFile)
  254. default:
  255. outSrcFiles = append(outSrcFiles, srcFile)
  256. }
  257. }
  258. // Process all aidl files together to support sharding them into one or more rules that produce srcjars.
  259. if len(aidlSrcs) > 0 {
  260. srcJarFiles := genAidl(ctx, aidlSrcs, flags.aidlFlags+aidlIncludeFlags, nil, flags.aidlDeps)
  261. outSrcFiles = append(outSrcFiles, srcJarFiles...)
  262. }
  263. return outSrcFiles
  264. }
  265. func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps {
  266. var deps deps
  267. sdkDep := decodeSdkDep(ctx, android.SdkContext(j))
  268. if sdkDep.invalidVersion {
  269. ctx.AddMissingDependencies(sdkDep.bootclasspath)
  270. ctx.AddMissingDependencies(sdkDep.java9Classpath)
  271. } else if sdkDep.useFiles {
  272. deps.bootClasspath = append(deps.bootClasspath, sdkDep.jars...)
  273. deps.aidlPreprocess = sdkDep.aidl
  274. } else {
  275. deps.aidlPreprocess = sdkDep.aidl
  276. }
  277. ctx.VisitDirectDeps(func(module android.Module) {
  278. otherName := ctx.OtherModuleName(module)
  279. tag := ctx.OtherModuleDependencyTag(module)
  280. switch tag {
  281. case bootClasspathTag:
  282. if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
  283. dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
  284. deps.bootClasspath = append(deps.bootClasspath, dep.ImplementationJars...)
  285. } else if sm, ok := module.(SystemModulesProvider); ok {
  286. // A system modules dependency has been added to the bootclasspath
  287. // so add its libs to the bootclasspath.
  288. deps.bootClasspath = append(deps.bootClasspath, sm.HeaderJars()...)
  289. } else {
  290. panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
  291. }
  292. case libTag, sdkLibTag:
  293. if dep, ok := module.(SdkLibraryDependency); ok {
  294. deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.SdkVersion(ctx))...)
  295. } else if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
  296. dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
  297. deps.classpath = append(deps.classpath, dep.HeaderJars...)
  298. deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs...)
  299. } else if dep, ok := module.(android.SourceFileProducer); ok {
  300. checkProducesJars(ctx, dep)
  301. deps.classpath = append(deps.classpath, dep.Srcs()...)
  302. } else {
  303. ctx.ModuleErrorf("depends on non-java module %q", otherName)
  304. }
  305. case java9LibTag:
  306. if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
  307. dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
  308. deps.java9Classpath = append(deps.java9Classpath, dep.HeaderJars...)
  309. } else {
  310. ctx.ModuleErrorf("depends on non-java module %q", otherName)
  311. }
  312. case systemModulesTag:
  313. if deps.systemModules != nil {
  314. panic("Found two system module dependencies")
  315. }
  316. sm := module.(SystemModulesProvider)
  317. outputDir, outputDeps := sm.OutputDirAndDeps()
  318. deps.systemModules = &systemModules{outputDir, outputDeps}
  319. }
  320. })
  321. // do not pass exclude_srcs directly when expanding srcFiles since exclude_srcs
  322. // may contain filegroup or genrule.
  323. srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
  324. j.implicits = append(j.implicits, srcFiles...)
  325. filterByPackage := func(srcs []android.Path, filterPackages []string) []android.Path {
  326. if filterPackages == nil {
  327. return srcs
  328. }
  329. filtered := []android.Path{}
  330. for _, src := range srcs {
  331. if src.Ext() != ".java" {
  332. // Don't filter-out non-Java (=generated sources) by package names. This is not ideal,
  333. // but otherwise metalava emits stub sources having references to the generated AIDL classes
  334. // in filtered-out pacages (e.g. com.android.internal.*).
  335. // TODO(b/141149570) We need to fix this by introducing default private constructors or
  336. // fixing metalava to not emit constructors having references to unknown classes.
  337. filtered = append(filtered, src)
  338. continue
  339. }
  340. packageName := strings.ReplaceAll(filepath.Dir(src.Rel()), "/", ".")
  341. if android.HasAnyPrefix(packageName, filterPackages) {
  342. filtered = append(filtered, src)
  343. }
  344. }
  345. return filtered
  346. }
  347. srcFiles = filterByPackage(srcFiles, j.properties.Filter_packages)
  348. aidlFlags := j.collectAidlFlags(ctx, deps)
  349. srcFiles = j.genSources(ctx, srcFiles, aidlFlags)
  350. // srcs may depend on some genrule output.
  351. j.srcJars = srcFiles.FilterByExt(".srcjar")
  352. j.srcJars = append(j.srcJars, deps.srcJars...)
  353. j.srcFiles = srcFiles.FilterOutByExt(".srcjar")
  354. j.srcFiles = append(j.srcFiles, deps.srcs...)
  355. if len(j.srcFiles) > 0 {
  356. j.sourcepaths = android.PathsForModuleSrc(ctx, []string{"."})
  357. }
  358. return deps
  359. }
  360. func (j *Javadoc) expandArgs(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
  361. var argFiles android.Paths
  362. argFilesMap := map[string]string{}
  363. argFileLabels := []string{}
  364. for _, label := range j.properties.Arg_files {
  365. var paths = android.PathsForModuleSrc(ctx, []string{label})
  366. if _, exists := argFilesMap[label]; !exists {
  367. argFilesMap[label] = strings.Join(cmd.PathsForInputs(paths), " ")
  368. argFileLabels = append(argFileLabels, label)
  369. argFiles = append(argFiles, paths...)
  370. } else {
  371. ctx.ModuleErrorf("multiple arg_files for %q, %q and %q",
  372. label, argFilesMap[label], paths)
  373. }
  374. }
  375. var argsPropertyName string
  376. flags := make([]string, 0)
  377. if j.properties.Args != nil && j.properties.Flags != nil {
  378. ctx.PropertyErrorf("args", "flags is set. Cannot set args")
  379. } else if args := proptools.String(j.properties.Args); args != "" {
  380. flags = append(flags, args)
  381. argsPropertyName = "args"
  382. } else {
  383. flags = append(flags, j.properties.Flags...)
  384. argsPropertyName = "flags"
  385. }
  386. for _, flag := range flags {
  387. expanded, err := android.Expand(flag, func(name string) (string, error) {
  388. if strings.HasPrefix(name, "location ") {
  389. label := strings.TrimSpace(strings.TrimPrefix(name, "location "))
  390. if paths, ok := argFilesMap[label]; ok {
  391. return paths, nil
  392. } else {
  393. return "", fmt.Errorf("unknown location label %q, expecting one of %q",
  394. label, strings.Join(argFileLabels, ", "))
  395. }
  396. } else if name == "genDir" {
  397. return android.PathForModuleGen(ctx).String(), nil
  398. }
  399. return "", fmt.Errorf("unknown variable '$(%s)'", name)
  400. })
  401. if err != nil {
  402. ctx.PropertyErrorf(argsPropertyName, "%s", err.Error())
  403. }
  404. cmd.Flag(expanded)
  405. }
  406. cmd.Implicits(argFiles)
  407. }
  408. func (j *Javadoc) DepsMutator(ctx android.BottomUpMutatorContext) {
  409. j.addDeps(ctx)
  410. }
  411. func (j *Javadoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
  412. deps := j.collectDeps(ctx)
  413. j.docZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"docs.zip")
  414. outDir := android.PathForModuleOut(ctx, "out")
  415. srcJarDir := android.PathForModuleOut(ctx, "srcjars")
  416. j.stubsSrcJar = nil
  417. rule := android.NewRuleBuilder(pctx, ctx)
  418. rule.Command().Text("rm -rf").Text(outDir.String())
  419. rule.Command().Text("mkdir -p").Text(outDir.String())
  420. srcJarList := zipSyncCmd(ctx, rule, srcJarDir, j.srcJars)
  421. javaVersion := getJavaVersion(ctx, String(j.properties.Java_version), android.SdkContext(j))
  422. cmd := javadocSystemModulesCmd(ctx, rule, j.srcFiles, outDir, srcJarDir, srcJarList,
  423. deps.systemModules, deps.classpath, j.sourcepaths)
  424. cmd.FlagWithArg("-source ", javaVersion.String()).
  425. Flag("-J-Xmx1024m").
  426. Flag("-XDignore.symbol.file").
  427. Flag("-Xdoclint:none")
  428. j.expandArgs(ctx, cmd)
  429. rule.Command().
  430. BuiltTool("soong_zip").
  431. Flag("-write_if_changed").
  432. Flag("-d").
  433. FlagWithOutput("-o ", j.docZip).
  434. FlagWithArg("-C ", outDir.String()).
  435. FlagWithArg("-D ", outDir.String())
  436. rule.Restat()
  437. zipSyncCleanupCmd(rule, srcJarDir)
  438. rule.Build("javadoc", "javadoc")
  439. }
  440. // Droiddoc
  441. type Droiddoc struct {
  442. Javadoc
  443. properties DroiddocProperties
  444. }
  445. // droiddoc converts .java source files to documentation using doclava or dokka.
  446. func DroiddocFactory() android.Module {
  447. module := &Droiddoc{}
  448. module.AddProperties(&module.properties,
  449. &module.Javadoc.properties)
  450. InitDroiddocModule(module, android.HostAndDeviceSupported)
  451. return module
  452. }
  453. // droiddoc_host converts .java source files to documentation using doclava or dokka.
  454. func DroiddocHostFactory() android.Module {
  455. module := &Droiddoc{}
  456. module.AddProperties(&module.properties,
  457. &module.Javadoc.properties)
  458. InitDroiddocModule(module, android.HostSupported)
  459. return module
  460. }
  461. func (d *Droiddoc) OutputFiles(tag string) (android.Paths, error) {
  462. switch tag {
  463. case "", ".docs.zip":
  464. return android.Paths{d.Javadoc.docZip}, nil
  465. default:
  466. return nil, fmt.Errorf("unsupported module reference tag %q", tag)
  467. }
  468. }
  469. func (d *Droiddoc) DepsMutator(ctx android.BottomUpMutatorContext) {
  470. d.Javadoc.addDeps(ctx)
  471. if String(d.properties.Custom_template) != "" {
  472. ctx.AddDependency(ctx.Module(), droiddocTemplateTag, String(d.properties.Custom_template))
  473. }
  474. }
  475. func (d *Droiddoc) doclavaDocsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, docletPath classpath) {
  476. buildNumberFile := ctx.Config().BuildNumberFile(ctx)
  477. // Droiddoc always gets "-source 1.8" because it doesn't support 1.9 sources. For modules with 1.9
  478. // sources, droiddoc will get sources produced by metalava which will have already stripped out the
  479. // 1.9 language features.
  480. cmd.FlagWithArg("-source ", getStubsJavaVersion().String()).
  481. Flag("-J-Xmx1600m").
  482. Flag("-J-XX:-OmitStackTraceInFastThrow").
  483. Flag("-XDignore.symbol.file").
  484. Flag("--ignore-source-errors").
  485. FlagWithArg("-doclet ", "com.google.doclava.Doclava").
  486. FlagWithInputList("-docletpath ", docletPath.Paths(), ":").
  487. FlagWithArg("-Xmaxerrs ", "10").
  488. FlagWithArg("-Xmaxwarns ", "10").
  489. Flag("-J--add-exports=jdk.javadoc/jdk.javadoc.internal.doclets.formats.html=ALL-UNNAMED").
  490. Flag("-J--add-exports=jdk.javadoc/jdk.javadoc.internal.tool=ALL-UNNAMED").
  491. Flag("-J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED").
  492. Flag("-J--add-exports=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED").
  493. Flag("-J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED").
  494. Flag("-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED").
  495. Flag("-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED").
  496. FlagWithArg("-hdf page.build ", ctx.Config().BuildId()+"-$(cat "+buildNumberFile.String()+")").OrderOnly(buildNumberFile).
  497. FlagWithArg("-hdf page.now ", `"$(date -d @$(cat `+ctx.Config().Getenv("BUILD_DATETIME_FILE")+`) "+%d %b %Y %k:%M")" `)
  498. if String(d.properties.Custom_template) == "" {
  499. // TODO: This is almost always droiddoc-templates-sdk
  500. ctx.PropertyErrorf("custom_template", "must specify a template")
  501. }
  502. ctx.VisitDirectDepsWithTag(droiddocTemplateTag, func(m android.Module) {
  503. if t, ok := m.(*ExportedDroiddocDir); ok {
  504. cmd.FlagWithArg("-templatedir ", t.dir.String()).Implicits(t.deps)
  505. } else {
  506. ctx.PropertyErrorf("custom_template", "module %q is not a droiddoc_exported_dir", ctx.OtherModuleName(m))
  507. }
  508. })
  509. if len(d.properties.Html_dirs) > 0 {
  510. htmlDir := android.PathForModuleSrc(ctx, d.properties.Html_dirs[0])
  511. cmd.FlagWithArg("-htmldir ", htmlDir.String()).
  512. Implicits(android.PathsForModuleSrc(ctx, []string{filepath.Join(d.properties.Html_dirs[0], "**/*")}))
  513. }
  514. if len(d.properties.Html_dirs) > 1 {
  515. htmlDir2 := android.PathForModuleSrc(ctx, d.properties.Html_dirs[1])
  516. cmd.FlagWithArg("-htmldir2 ", htmlDir2.String()).
  517. Implicits(android.PathsForModuleSrc(ctx, []string{filepath.Join(d.properties.Html_dirs[1], "**/*")}))
  518. }
  519. if len(d.properties.Html_dirs) > 2 {
  520. ctx.PropertyErrorf("html_dirs", "Droiddoc only supports up to 2 html dirs")
  521. }
  522. knownTags := android.PathsForModuleSrc(ctx, d.properties.Knowntags)
  523. cmd.FlagForEachInput("-knowntags ", knownTags)
  524. cmd.FlagForEachArg("-hdf ", d.properties.Hdf)
  525. if String(d.properties.Proofread_file) != "" {
  526. proofreadFile := android.PathForModuleOut(ctx, String(d.properties.Proofread_file))
  527. cmd.FlagWithOutput("-proofread ", proofreadFile)
  528. }
  529. if String(d.properties.Todo_file) != "" {
  530. // tricky part:
  531. // we should not compute full path for todo_file through PathForModuleOut().
  532. // the non-standard doclet will get the full path relative to "-o".
  533. cmd.FlagWithArg("-todo ", String(d.properties.Todo_file)).
  534. ImplicitOutput(android.PathForModuleOut(ctx, String(d.properties.Todo_file)))
  535. }
  536. if String(d.properties.Resourcesdir) != "" {
  537. // TODO: should we add files under resourcesDir to the implicits? It seems that
  538. // resourcesDir is one sub dir of htmlDir
  539. resourcesDir := android.PathForModuleSrc(ctx, String(d.properties.Resourcesdir))
  540. cmd.FlagWithArg("-resourcesdir ", resourcesDir.String())
  541. }
  542. if String(d.properties.Resourcesoutdir) != "" {
  543. // TODO: it seems -resourceoutdir reference/android/images/ didn't get generated anywhere.
  544. cmd.FlagWithArg("-resourcesoutdir ", String(d.properties.Resourcesoutdir))
  545. }
  546. }
  547. func (d *Droiddoc) postDoclavaCmds(ctx android.ModuleContext, rule *android.RuleBuilder) {
  548. if String(d.properties.Static_doc_index_redirect) != "" {
  549. staticDocIndexRedirect := android.PathForModuleSrc(ctx, String(d.properties.Static_doc_index_redirect))
  550. rule.Command().Text("cp").
  551. Input(staticDocIndexRedirect).
  552. Output(android.PathForModuleOut(ctx, "out", "index.html"))
  553. }
  554. if String(d.properties.Static_doc_properties) != "" {
  555. staticDocProperties := android.PathForModuleSrc(ctx, String(d.properties.Static_doc_properties))
  556. rule.Command().Text("cp").
  557. Input(staticDocProperties).
  558. Output(android.PathForModuleOut(ctx, "out", "source.properties"))
  559. }
  560. }
  561. func javadocCmd(ctx android.ModuleContext, rule *android.RuleBuilder, srcs android.Paths,
  562. outDir, srcJarDir, srcJarList android.Path, sourcepaths android.Paths) *android.RuleBuilderCommand {
  563. cmd := rule.Command().
  564. BuiltTool("soong_javac_wrapper").Tool(config.JavadocCmd(ctx)).
  565. Flag(config.JavacVmFlags).
  566. FlagWithArg("-encoding ", "UTF-8").
  567. FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "javadoc.rsp"), srcs).
  568. FlagWithInput("@", srcJarList)
  569. // TODO(ccross): Remove this if- statement once we finish migration for all Doclava
  570. // based stubs generation.
  571. // In the future, all the docs generation depends on Metalava stubs (droidstubs) srcjar
  572. // dir. We need add the srcjar dir to -sourcepath arg, so that Javadoc can figure out
  573. // the correct package name base path.
  574. if len(sourcepaths) > 0 {
  575. cmd.FlagWithList("-sourcepath ", sourcepaths.Strings(), ":")
  576. } else {
  577. cmd.FlagWithArg("-sourcepath ", srcJarDir.String())
  578. }
  579. cmd.FlagWithArg("-d ", outDir.String()).
  580. Flag("-quiet")
  581. return cmd
  582. }
  583. func javadocSystemModulesCmd(ctx android.ModuleContext, rule *android.RuleBuilder, srcs android.Paths,
  584. outDir, srcJarDir, srcJarList android.Path, systemModules *systemModules,
  585. classpath classpath, sourcepaths android.Paths) *android.RuleBuilderCommand {
  586. cmd := javadocCmd(ctx, rule, srcs, outDir, srcJarDir, srcJarList, sourcepaths)
  587. flag, deps := systemModules.FormJavaSystemModulesPath(ctx.Device())
  588. cmd.Flag(flag).Implicits(deps)
  589. cmd.FlagWithArg("--patch-module ", "java.base=.")
  590. if len(classpath) > 0 {
  591. cmd.FlagWithInputList("-classpath ", classpath.Paths(), ":")
  592. }
  593. return cmd
  594. }
  595. func javadocBootclasspathCmd(ctx android.ModuleContext, rule *android.RuleBuilder, srcs android.Paths,
  596. outDir, srcJarDir, srcJarList android.Path, bootclasspath, classpath classpath,
  597. sourcepaths android.Paths) *android.RuleBuilderCommand {
  598. cmd := javadocCmd(ctx, rule, srcs, outDir, srcJarDir, srcJarList, sourcepaths)
  599. if len(bootclasspath) == 0 && ctx.Device() {
  600. // explicitly specify -bootclasspath "" if the bootclasspath is empty to
  601. // ensure java does not fall back to the default bootclasspath.
  602. cmd.FlagWithArg("-bootclasspath ", `""`)
  603. } else if len(bootclasspath) > 0 {
  604. cmd.FlagWithInputList("-bootclasspath ", bootclasspath.Paths(), ":")
  605. }
  606. if len(classpath) > 0 {
  607. cmd.FlagWithInputList("-classpath ", classpath.Paths(), ":")
  608. }
  609. return cmd
  610. }
  611. func dokkaCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
  612. outDir, srcJarDir android.Path, bootclasspath, classpath classpath) *android.RuleBuilderCommand {
  613. // Dokka doesn't support bootClasspath, so combine these two classpath vars for Dokka.
  614. dokkaClasspath := append(bootclasspath.Paths(), classpath.Paths()...)
  615. return rule.Command().
  616. BuiltTool("dokka").
  617. Flag(config.JavacVmFlags).
  618. Flag("-J--add-opens=java.base/java.lang=ALL-UNNAMED").
  619. Flag(srcJarDir.String()).
  620. FlagWithInputList("-classpath ", dokkaClasspath, ":").
  621. FlagWithArg("-format ", "dac").
  622. FlagWithArg("-dacRoot ", "/reference/kotlin").
  623. FlagWithArg("-output ", outDir.String())
  624. }
  625. func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
  626. deps := d.Javadoc.collectDeps(ctx)
  627. d.Javadoc.docZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"docs.zip")
  628. jsilver := ctx.Config().HostJavaToolPath(ctx, "jsilver.jar")
  629. doclava := ctx.Config().HostJavaToolPath(ctx, "doclava.jar")
  630. outDir := android.PathForModuleOut(ctx, "out")
  631. srcJarDir := android.PathForModuleOut(ctx, "srcjars")
  632. rule := android.NewRuleBuilder(pctx, ctx)
  633. srcJarList := zipSyncCmd(ctx, rule, srcJarDir, d.Javadoc.srcJars)
  634. var cmd *android.RuleBuilderCommand
  635. if Bool(d.properties.Dokka_enabled) {
  636. cmd = dokkaCmd(ctx, rule, outDir, srcJarDir, deps.bootClasspath, deps.classpath)
  637. } else {
  638. cmd = javadocBootclasspathCmd(ctx, rule, d.Javadoc.srcFiles, outDir, srcJarDir, srcJarList,
  639. deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths)
  640. }
  641. d.expandArgs(ctx, cmd)
  642. if d.properties.Compat_config != nil {
  643. compatConfig := android.PathForModuleSrc(ctx, String(d.properties.Compat_config))
  644. cmd.FlagWithInput("-compatconfig ", compatConfig)
  645. }
  646. var desc string
  647. if Bool(d.properties.Dokka_enabled) {
  648. desc = "dokka"
  649. } else {
  650. d.doclavaDocsFlags(ctx, cmd, classpath{jsilver, doclava})
  651. for _, o := range d.Javadoc.properties.Out {
  652. cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
  653. }
  654. d.postDoclavaCmds(ctx, rule)
  655. desc = "doclava"
  656. }
  657. rule.Command().
  658. BuiltTool("soong_zip").
  659. Flag("-write_if_changed").
  660. Flag("-d").
  661. FlagWithOutput("-o ", d.docZip).
  662. FlagWithArg("-C ", outDir.String()).
  663. FlagWithArg("-D ", outDir.String())
  664. rule.Restat()
  665. zipSyncCleanupCmd(rule, srcJarDir)
  666. rule.Build("javadoc", desc)
  667. }
  668. // Exported Droiddoc Directory
  669. var droiddocTemplateTag = dependencyTag{name: "droiddoc-template"}
  670. type ExportedDroiddocDirProperties struct {
  671. // path to the directory containing Droiddoc related files.
  672. Path *string
  673. }
  674. type ExportedDroiddocDir struct {
  675. android.ModuleBase
  676. properties ExportedDroiddocDirProperties
  677. deps android.Paths
  678. dir android.Path
  679. }
  680. // droiddoc_exported_dir exports a directory of html templates or nullability annotations for use by doclava.
  681. func ExportedDroiddocDirFactory() android.Module {
  682. module := &ExportedDroiddocDir{}
  683. module.AddProperties(&module.properties)
  684. android.InitAndroidModule(module)
  685. return module
  686. }
  687. func (d *ExportedDroiddocDir) DepsMutator(android.BottomUpMutatorContext) {}
  688. func (d *ExportedDroiddocDir) GenerateAndroidBuildActions(ctx android.ModuleContext) {
  689. path := String(d.properties.Path)
  690. d.dir = android.PathForModuleSrc(ctx, path)
  691. d.deps = android.PathsForModuleSrc(ctx, []string{filepath.Join(path, "**/*")})
  692. }
  693. // Defaults
  694. type DocDefaults struct {
  695. android.ModuleBase
  696. android.DefaultsModuleBase
  697. }
  698. func DocDefaultsFactory() android.Module {
  699. module := &DocDefaults{}
  700. module.AddProperties(
  701. &JavadocProperties{},
  702. &DroiddocProperties{},
  703. )
  704. android.InitDefaultsModule(module)
  705. return module
  706. }
  707. func zipSyncCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
  708. srcJarDir android.ModuleOutPath, srcJars android.Paths) android.OutputPath {
  709. cmd := rule.Command()
  710. cmd.Text("rm -rf").Text(cmd.PathForOutput(srcJarDir))
  711. cmd = rule.Command()
  712. cmd.Text("mkdir -p").Text(cmd.PathForOutput(srcJarDir))
  713. srcJarList := srcJarDir.Join(ctx, "list")
  714. rule.Temporary(srcJarList)
  715. cmd = rule.Command()
  716. cmd.BuiltTool("zipsync").
  717. FlagWithArg("-d ", cmd.PathForOutput(srcJarDir)).
  718. FlagWithOutput("-l ", srcJarList).
  719. FlagWithArg("-f ", `"*.java"`).
  720. Inputs(srcJars)
  721. return srcJarList
  722. }
  723. func zipSyncCleanupCmd(rule *android.RuleBuilder, srcJarDir android.ModuleOutPath) {
  724. rule.Command().Text("rm -rf").Text(srcJarDir.String())
  725. }