blob: 6a28cfb66c059cbb7033ffd6d24fa8961fc796c7 [file] [log] [blame]
Nan Zhang581fd212018-01-10 16:06:12 -08001// 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
15package java
16
17import (
18 "android/soong/android"
19 "android/soong/java/config"
20 "fmt"
Nan Zhangb2b33de2018-02-23 11:18:47 -080021 "path/filepath"
Nan Zhang46130972018-06-04 11:28:01 -070022 "runtime"
Nan Zhang581fd212018-01-10 16:06:12 -080023 "strings"
24
25 "github.com/google/blueprint"
26)
27
28var (
29 javadoc = pctx.AndroidStaticRule("javadoc",
30 blueprint.RuleParams{
31 Command: `rm -rf "$outDir" "$srcJarDir" "$stubsDir" && mkdir -p "$outDir" "$srcJarDir" "$stubsDir" && ` +
Colin Cross436b7652018-03-15 16:24:10 -070032 `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
Nan Zhangaf322cc2018-06-19 15:15:38 -070033 `${config.JavadocCmd} -encoding UTF-8 @$out.rsp @$srcJarDir/list ` +
Nan Zhang581fd212018-01-10 16:06:12 -080034 `$opts $bootclasspathArgs $classpathArgs -sourcepath $sourcepath ` +
35 `-d $outDir -quiet && ` +
36 `${config.SoongZipCmd} -write_if_changed -d -o $docZip -C $outDir -D $outDir && ` +
Nan Zhange2ba5d42018-07-11 15:16:55 -070037 `${config.SoongZipCmd} -write_if_changed -jar -o $out -C $stubsDir -D $stubsDir $postDoclavaCmds`,
Nan Zhang581fd212018-01-10 16:06:12 -080038 CommandDeps: []string{
Colin Cross436b7652018-03-15 16:24:10 -070039 "${config.ZipSyncCmd}",
Nan Zhang581fd212018-01-10 16:06:12 -080040 "${config.JavadocCmd}",
41 "${config.SoongZipCmd}",
Nan Zhang581fd212018-01-10 16:06:12 -080042 },
43 Rspfile: "$out.rsp",
44 RspfileContent: "$in",
45 Restat: true,
46 },
Nan Zhangaf322cc2018-06-19 15:15:38 -070047 "outDir", "srcJarDir", "stubsDir", "srcJars", "opts",
Nan Zhange2ba5d42018-07-11 15:16:55 -070048 "bootclasspathArgs", "classpathArgs", "sourcepath", "docZip", "postDoclavaCmds")
Nan Zhang61819ce2018-05-04 18:49:16 -070049
50 apiCheck = pctx.AndroidStaticRule("apiCheck",
51 blueprint.RuleParams{
52 Command: `( ${config.ApiCheckCmd} -JXmx1024m -J"classpath $classpath" $opts ` +
53 `$apiFile $apiFileToCheck $removedApiFile $removedApiFileToCheck ` +
Jiyong Parkeeb8a642018-05-12 22:21:20 +090054 `&& touch $out ) || (echo -e "$msg" ; exit 38)`,
Nan Zhang61819ce2018-05-04 18:49:16 -070055 CommandDeps: []string{
56 "${config.ApiCheckCmd}",
57 },
58 },
59 "classpath", "opts", "apiFile", "apiFileToCheck", "removedApiFile", "removedApiFileToCheck", "msg")
60
61 updateApi = pctx.AndroidStaticRule("updateApi",
62 blueprint.RuleParams{
63 Command: `( ( cp -f $apiFileToCheck $apiFile && cp -f $removedApiFileToCheck $removedApiFile ) ` +
64 `&& touch $out ) || (echo failed to update public API ; exit 38)`,
65 },
66 "apiFile", "apiFileToCheck", "removedApiFile", "removedApiFileToCheck")
Nan Zhang79614d12018-04-19 18:03:39 -070067
68 metalava = pctx.AndroidStaticRule("metalava",
69 blueprint.RuleParams{
Nan Zhangde860a42018-08-08 16:32:21 -070070 Command: `rm -rf "$outDir" "$srcJarDir" "$stubsDir" "$docStubsDir" && ` +
71 `mkdir -p "$outDir" "$srcJarDir" "$stubsDir" "$docStubsDir" && ` +
Nan Zhang79614d12018-04-19 18:03:39 -070072 `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
Nan Zhang357466b2018-04-17 17:38:36 -070073 `${config.JavaCmd} -jar ${config.MetalavaJar} -encoding UTF-8 -source $javaVersion @$out.rsp @$srcJarDir/list ` +
Nan Zhang16c0a312018-06-13 17:42:48 -070074 `$bootclasspathArgs $classpathArgs -sourcepath $sourcepath --no-banner --color --quiet ` +
75 `--stubs $stubsDir $opts && ` +
Nan Zhang79614d12018-04-19 18:03:39 -070076 `${config.SoongZipCmd} -write_if_changed -d -o $docZip -C $outDir -D $outDir && ` +
77 `${config.SoongZipCmd} -write_if_changed -jar -o $out -C $stubsDir -D $stubsDir`,
78 CommandDeps: []string{
79 "${config.ZipSyncCmd}",
80 "${config.JavaCmd}",
81 "${config.MetalavaJar}",
82 "${config.JavadocCmd}",
83 "${config.SoongZipCmd}",
84 },
85 Rspfile: "$out.rsp",
86 RspfileContent: "$in",
87 Restat: true,
88 },
Nan Zhangde860a42018-08-08 16:32:21 -070089 "outDir", "srcJarDir", "stubsDir", "docStubsDir", "srcJars", "javaVersion", "bootclasspathArgs",
Nan Zhang357466b2018-04-17 17:38:36 -070090 "classpathArgs", "sourcepath", "opts", "docZip")
Nan Zhang581fd212018-01-10 16:06:12 -080091)
92
93func init() {
Nan Zhangb2b33de2018-02-23 11:18:47 -080094 android.RegisterModuleType("doc_defaults", DocDefaultsFactory)
95
Nan Zhang581fd212018-01-10 16:06:12 -080096 android.RegisterModuleType("droiddoc", DroiddocFactory)
97 android.RegisterModuleType("droiddoc_host", DroiddocHostFactory)
Nan Zhangf4936b02018-08-01 15:00:28 -070098 android.RegisterModuleType("droiddoc_exported_dir", ExportedDroiddocDirFactory)
Nan Zhang581fd212018-01-10 16:06:12 -080099 android.RegisterModuleType("javadoc", JavadocFactory)
100 android.RegisterModuleType("javadoc_host", JavadocHostFactory)
101}
102
Colin Crossa1ce2a02018-06-20 15:19:39 -0700103var (
104 srcsLibTag = dependencyTag{name: "sources from javalib"}
105)
106
Nan Zhang581fd212018-01-10 16:06:12 -0800107type JavadocProperties struct {
108 // list of source files used to compile the Java module. May be .java, .logtags, .proto,
109 // or .aidl files.
110 Srcs []string `android:"arch_variant"`
111
112 // list of directories rooted at the Android.bp file that will
113 // be added to the search paths for finding source files when passing package names.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800114 Local_sourcepaths []string
Nan Zhang581fd212018-01-10 16:06:12 -0800115
116 // list of source files that should not be used to build the Java module.
117 // This is most useful in the arch/multilib variants to remove non-common files
118 // filegroup or genrule can be included within this property.
119 Exclude_srcs []string `android:"arch_variant"`
120
Nan Zhangb2b33de2018-02-23 11:18:47 -0800121 // list of java libraries that will be in the classpath.
Nan Zhang581fd212018-01-10 16:06:12 -0800122 Libs []string `android:"arch_variant"`
123
Nan Zhange66c7272018-03-06 12:59:27 -0800124 // don't build against the framework libraries (legacy-test, core-junit,
125 // ext, and framework for device targets)
126 No_framework_libs *bool
127
Nan Zhangb2b33de2018-02-23 11:18:47 -0800128 // the java library (in classpath) for documentation that provides java srcs and srcjars.
129 Srcs_lib *string
130
131 // the base dirs under srcs_lib will be scanned for java srcs.
132 Srcs_lib_whitelist_dirs []string
133
134 // the sub dirs under srcs_lib_whitelist_dirs will be scanned for java srcs.
135 Srcs_lib_whitelist_pkgs []string
136
Nan Zhang581fd212018-01-10 16:06:12 -0800137 // If set to false, don't allow this module(-docs.zip) to be exported. Defaults to true.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800138 Installable *bool
Nan Zhang581fd212018-01-10 16:06:12 -0800139
140 // if not blank, set to the version of the sdk to compile against
141 Sdk_version *string `android:"arch_variant"`
Jiyong Park1e440682018-05-23 18:42:04 +0900142
143 Aidl struct {
144 // Top level directories to pass to aidl tool
145 Include_dirs []string
146
147 // Directories rooted at the Android.bp file to pass to aidl tool
148 Local_include_dirs []string
149 }
Nan Zhang357466b2018-04-17 17:38:36 -0700150
151 // If not blank, set the java version passed to javadoc as -source
152 Java_version *string
Nan Zhang581fd212018-01-10 16:06:12 -0800153}
154
Nan Zhang61819ce2018-05-04 18:49:16 -0700155type ApiToCheck struct {
Jiyong Parkeeb8a642018-05-12 22:21:20 +0900156 // path to the API txt file that the new API extracted from source code is checked
157 // against. The path can be local to the module or from other module (via :module syntax).
Nan Zhang61819ce2018-05-04 18:49:16 -0700158 Api_file *string
159
Jiyong Parkeeb8a642018-05-12 22:21:20 +0900160 // path to the API txt file that the new @removed API extractd from source code is
161 // checked against. The path can be local to the module or from other module (via
162 // :module syntax).
Nan Zhang61819ce2018-05-04 18:49:16 -0700163 Removed_api_file *string
164
Jiyong Parkeeb8a642018-05-12 22:21:20 +0900165 // Arguments to the apicheck tool.
Nan Zhang61819ce2018-05-04 18:49:16 -0700166 Args *string
167}
168
Nan Zhang581fd212018-01-10 16:06:12 -0800169type DroiddocProperties struct {
170 // directory relative to top of the source tree that contains doc templates files.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800171 Custom_template *string
Nan Zhang581fd212018-01-10 16:06:12 -0800172
Nan Zhanga40da042018-08-01 12:48:00 -0700173 // directories under current module source which contains html/jd files.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800174 Html_dirs []string
Nan Zhang581fd212018-01-10 16:06:12 -0800175
176 // set a value in the Clearsilver hdf namespace.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800177 Hdf []string
Nan Zhang581fd212018-01-10 16:06:12 -0800178
179 // proofread file contains all of the text content of the javadocs concatenated into one file,
180 // suitable for spell-checking and other goodness.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800181 Proofread_file *string
Nan Zhang581fd212018-01-10 16:06:12 -0800182
183 // a todo file lists the program elements that are missing documentation.
184 // At some point, this might be improved to show more warnings.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800185 Todo_file *string
186
187 // directory under current module source that provide additional resources (images).
188 Resourcesdir *string
189
190 // resources output directory under out/soong/.intermediates.
191 Resourcesoutdir *string
Nan Zhang581fd212018-01-10 16:06:12 -0800192
193 // local files that are used within user customized droiddoc options.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800194 Arg_files []string
Nan Zhang581fd212018-01-10 16:06:12 -0800195
196 // user customized droiddoc args.
197 // Available variables for substitution:
198 //
199 // $(location <label>): the path to the arg_files with name <label>
Nan Zhangb2b33de2018-02-23 11:18:47 -0800200 Args *string
Nan Zhang581fd212018-01-10 16:06:12 -0800201
202 // names of the output files used in args that will be generated
Nan Zhangb2b33de2018-02-23 11:18:47 -0800203 Out []string
Nan Zhang581fd212018-01-10 16:06:12 -0800204
Nan Zhange2ba5d42018-07-11 15:16:55 -0700205 // if set to true, collect the values used by the Dev tools and
206 // write them in files packaged with the SDK. Defaults to false.
207 Write_sdk_values *bool
208
209 // index.html under current module will be copied to docs out dir, if not null.
210 Static_doc_index_redirect *string
211
212 // source.properties under current module will be copied to docs out dir, if not null.
213 Static_doc_properties *string
214
Nan Zhang581fd212018-01-10 16:06:12 -0800215 // a list of files under current module source dir which contains known tags in Java sources.
216 // filegroup or genrule can be included within this property.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800217 Knowntags []string
Nan Zhang28c68b92018-03-13 16:17:01 -0700218
219 // the tag name used to distinguish if the API files belong to public/system/test.
220 Api_tag_name *string
221
222 // the generated public API filename by Doclava.
223 Api_filename *string
224
David Brazdilfbe4cc32018-05-31 13:56:46 +0100225 // the generated public Dex API filename by Doclava.
226 Dex_api_filename *string
227
Nan Zhang28c68b92018-03-13 16:17:01 -0700228 // the generated private API filename by Doclava.
229 Private_api_filename *string
230
231 // the generated private Dex API filename by Doclava.
232 Private_dex_api_filename *string
233
234 // the generated removed API filename by Doclava.
235 Removed_api_filename *string
236
David Brazdilaac0c3c2018-04-24 16:23:29 +0100237 // the generated removed Dex API filename by Doclava.
238 Removed_dex_api_filename *string
239
Mathew Inwood76c3de12018-06-22 15:28:11 +0100240 // mapping of dex signatures to source file and line number. This is a temporary property and
241 // will be deleted; you probably shouldn't be using it.
242 Dex_mapping_filename *string
243
Nan Zhang28c68b92018-03-13 16:17:01 -0700244 // the generated exact API filename by Doclava.
245 Exact_api_filename *string
Nan Zhang853f4202018-04-12 16:55:56 -0700246
247 // if set to false, don't allow droiddoc to generate stubs source files. Defaults to true.
248 Create_stubs *bool
Nan Zhang61819ce2018-05-04 18:49:16 -0700249
250 Check_api struct {
251 Last_released ApiToCheck
252
253 Current ApiToCheck
254 }
Nan Zhang79614d12018-04-19 18:03:39 -0700255
256 // if set to true, create stubs through Metalava instead of Doclava. Javadoc/Doclava is
257 // currently still used for documentation generation, and will be replaced by Dokka soon.
258 Metalava_enabled *bool
259
260 // user can specify the version of previous released API file in order to do compatibility check.
261 Metalava_previous_api *string
262
263 // is set to true, Metalava will allow framework SDK to contain annotations.
264 Metalava_annotations_enabled *bool
265
Pete Gillinb13a0152018-07-19 17:56:49 +0100266 // a list of top-level directories containing files to merge annotations from.
267 Metalava_merge_annotations_dirs []string
Nan Zhang86d2d552018-08-09 15:33:27 -0700268
269 // if set to true, generate docs through Dokka instead of Doclava. Valid only when
270 // metalava_enabled is set to true.
271 Dokka_enabled *bool
Nan Zhang581fd212018-01-10 16:06:12 -0800272}
273
Nan Zhanga40da042018-08-01 12:48:00 -0700274//
275// Common flags passed down to build rule
276//
277type droiddocBuilderFlags struct {
Nan Zhang86d2d552018-08-09 15:33:27 -0700278 args string
279 bootClasspathArgs string
280 classpathArgs string
281 dokkaClasspathArgs string
282 aidlFlags string
Nan Zhanga40da042018-08-01 12:48:00 -0700283
Nan Zhanga40da042018-08-01 12:48:00 -0700284 doclavaStubsFlags string
Nan Zhang86d2d552018-08-09 15:33:27 -0700285 doclavaDocsFlags string
Nan Zhanga40da042018-08-01 12:48:00 -0700286 postDoclavaCmds string
287
Nan Zhanga40da042018-08-01 12:48:00 -0700288 metalavaStubsFlags string
Nan Zhang86d2d552018-08-09 15:33:27 -0700289 metalavaAnnotationsFlags string
290 metalavaJavadocFlags string
Nan Zhanga40da042018-08-01 12:48:00 -0700291
Nan Zhang86d2d552018-08-09 15:33:27 -0700292 metalavaDokkaFlags string
Nan Zhanga40da042018-08-01 12:48:00 -0700293}
294
295func InitDroiddocModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
296 android.InitAndroidArchModule(module, hod, android.MultilibCommon)
297 android.InitDefaultableModule(module)
298}
299
300//
301// Javadoc
302//
Nan Zhang581fd212018-01-10 16:06:12 -0800303type Javadoc struct {
304 android.ModuleBase
305 android.DefaultableModuleBase
306
307 properties JavadocProperties
308
309 srcJars android.Paths
310 srcFiles android.Paths
311 sourcepaths android.Paths
312
Nan Zhangccff0f72018-03-08 17:26:16 -0800313 docZip android.WritablePath
314 stubsSrcJar android.WritablePath
Nan Zhang581fd212018-01-10 16:06:12 -0800315}
316
Nan Zhangb2b33de2018-02-23 11:18:47 -0800317func (j *Javadoc) Srcs() android.Paths {
318 return android.Paths{j.stubsSrcJar}
319}
320
Nan Zhang581fd212018-01-10 16:06:12 -0800321func JavadocFactory() android.Module {
322 module := &Javadoc{}
323
324 module.AddProperties(&module.properties)
325
326 InitDroiddocModule(module, android.HostAndDeviceSupported)
327 return module
328}
329
330func JavadocHostFactory() android.Module {
331 module := &Javadoc{}
332
333 module.AddProperties(&module.properties)
334
335 InitDroiddocModule(module, android.HostSupported)
336 return module
337}
338
Nan Zhanga40da042018-08-01 12:48:00 -0700339var _ android.SourceFileProducer = (*Javadoc)(nil)
Nan Zhang581fd212018-01-10 16:06:12 -0800340
Colin Cross83bb3162018-06-25 15:48:06 -0700341func (j *Javadoc) sdkVersion() string {
342 return String(j.properties.Sdk_version)
343}
344
345func (j *Javadoc) minSdkVersion() string {
346 return j.sdkVersion()
347}
348
Nan Zhang581fd212018-01-10 16:06:12 -0800349func (j *Javadoc) addDeps(ctx android.BottomUpMutatorContext) {
350 if ctx.Device() {
Colin Cross83bb3162018-06-25 15:48:06 -0700351 sdkDep := decodeSdkDep(ctx, sdkContext(j))
Nan Zhang581fd212018-01-10 16:06:12 -0800352 if sdkDep.useDefaultLibs {
353 ctx.AddDependency(ctx.Module(), bootClasspathTag, config.DefaultBootclasspathLibraries...)
Nan Zhang357466b2018-04-17 17:38:36 -0700354 if ctx.Config().TargetOpenJDK9() {
355 ctx.AddDependency(ctx.Module(), systemModulesTag, config.DefaultSystemModules)
356 }
Nan Zhang9cbe6772018-03-21 17:56:39 -0700357 if !Bool(j.properties.No_framework_libs) {
Nan Zhang77a69ec2018-08-02 16:28:26 -0700358 ctx.AddDependency(ctx.Module(), libTag, config.DefaultLibraries...)
Nan Zhange66c7272018-03-06 12:59:27 -0800359 }
Nan Zhang581fd212018-01-10 16:06:12 -0800360 } else if sdkDep.useModule {
Nan Zhang357466b2018-04-17 17:38:36 -0700361 if ctx.Config().TargetOpenJDK9() {
362 ctx.AddDependency(ctx.Module(), systemModulesTag, sdkDep.systemModules)
363 }
Colin Cross86a60ae2018-05-29 14:44:55 -0700364 ctx.AddDependency(ctx.Module(), bootClasspathTag, sdkDep.modules...)
Nan Zhang581fd212018-01-10 16:06:12 -0800365 }
366 }
367
368 ctx.AddDependency(ctx.Module(), libTag, j.properties.Libs...)
Colin Crossa1ce2a02018-06-20 15:19:39 -0700369 if j.properties.Srcs_lib != nil {
370 ctx.AddDependency(ctx.Module(), srcsLibTag, *j.properties.Srcs_lib)
371 }
Nan Zhang581fd212018-01-10 16:06:12 -0800372
373 android.ExtractSourcesDeps(ctx, j.properties.Srcs)
374
375 // exclude_srcs may contain filegroup or genrule.
376 android.ExtractSourcesDeps(ctx, j.properties.Exclude_srcs)
377}
378
Nan Zhangb2b33de2018-02-23 11:18:47 -0800379func (j *Javadoc) genWhitelistPathPrefixes(whitelistPathPrefixes map[string]bool) {
380 for _, dir := range j.properties.Srcs_lib_whitelist_dirs {
381 for _, pkg := range j.properties.Srcs_lib_whitelist_pkgs {
Jiyong Park82484c02018-04-23 21:41:26 +0900382 // convert foo.bar.baz to foo/bar/baz
383 pkgAsPath := filepath.Join(strings.Split(pkg, ".")...)
384 prefix := filepath.Join(dir, pkgAsPath)
Nan Zhangb2b33de2018-02-23 11:18:47 -0800385 if _, found := whitelistPathPrefixes[prefix]; !found {
386 whitelistPathPrefixes[prefix] = true
387 }
388 }
389 }
390}
391
Nan Zhanga40da042018-08-01 12:48:00 -0700392func (j *Javadoc) collectAidlFlags(ctx android.ModuleContext, deps deps) droiddocBuilderFlags {
393 var flags droiddocBuilderFlags
Jiyong Park1e440682018-05-23 18:42:04 +0900394
395 // aidl flags.
396 aidlFlags := j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs)
397 if len(aidlFlags) > 0 {
398 // optimization.
399 ctx.Variable(pctx, "aidlFlags", strings.Join(aidlFlags, " "))
400 flags.aidlFlags = "$aidlFlags"
401 }
402
403 return flags
404}
405
406func (j *Javadoc) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.OptionalPath,
407 aidlIncludeDirs android.Paths) []string {
408
409 aidlIncludes := android.PathsForModuleSrc(ctx, j.properties.Aidl.Local_include_dirs)
410 aidlIncludes = append(aidlIncludes, android.PathsForSource(ctx, j.properties.Aidl.Include_dirs)...)
411
412 var flags []string
413 if aidlPreprocess.Valid() {
414 flags = append(flags, "-p"+aidlPreprocess.String())
415 } else {
416 flags = append(flags, android.JoinWithPrefix(aidlIncludeDirs.Strings(), "-I"))
417 }
418
419 flags = append(flags, android.JoinWithPrefix(aidlIncludes.Strings(), "-I"))
420 flags = append(flags, "-I"+android.PathForModuleSrc(ctx).String())
421 if src := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "src"); src.Valid() {
422 flags = append(flags, "-I"+src.String())
423 }
424
425 return flags
426}
427
428func (j *Javadoc) genSources(ctx android.ModuleContext, srcFiles android.Paths,
Nan Zhanga40da042018-08-01 12:48:00 -0700429 flags droiddocBuilderFlags) android.Paths {
Jiyong Park1e440682018-05-23 18:42:04 +0900430
431 outSrcFiles := make(android.Paths, 0, len(srcFiles))
432
433 for _, srcFile := range srcFiles {
434 switch srcFile.Ext() {
435 case ".aidl":
436 javaFile := genAidl(ctx, srcFile, flags.aidlFlags)
437 outSrcFiles = append(outSrcFiles, javaFile)
438 default:
439 outSrcFiles = append(outSrcFiles, srcFile)
440 }
441 }
442
443 return outSrcFiles
444}
445
Nan Zhang581fd212018-01-10 16:06:12 -0800446func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps {
447 var deps deps
448
Colin Cross83bb3162018-06-25 15:48:06 -0700449 sdkDep := decodeSdkDep(ctx, sdkContext(j))
Nan Zhang581fd212018-01-10 16:06:12 -0800450 if sdkDep.invalidVersion {
Colin Cross86a60ae2018-05-29 14:44:55 -0700451 ctx.AddMissingDependencies(sdkDep.modules)
Nan Zhang581fd212018-01-10 16:06:12 -0800452 } else if sdkDep.useFiles {
Colin Cross86a60ae2018-05-29 14:44:55 -0700453 deps.bootClasspath = append(deps.bootClasspath, sdkDep.jars...)
Nan Zhang581fd212018-01-10 16:06:12 -0800454 }
455
456 ctx.VisitDirectDeps(func(module android.Module) {
457 otherName := ctx.OtherModuleName(module)
458 tag := ctx.OtherModuleDependencyTag(module)
459
Colin Cross2d24c1b2018-05-23 10:59:18 -0700460 switch tag {
461 case bootClasspathTag:
462 if dep, ok := module.(Dependency); ok {
Nan Zhang581fd212018-01-10 16:06:12 -0800463 deps.bootClasspath = append(deps.bootClasspath, dep.ImplementationJars()...)
Colin Cross2d24c1b2018-05-23 10:59:18 -0700464 } else {
465 panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
466 }
467 case libTag:
468 switch dep := module.(type) {
469 case Dependency:
Nan Zhang581fd212018-01-10 16:06:12 -0800470 deps.classpath = append(deps.classpath, dep.ImplementationJars()...)
Colin Cross2d24c1b2018-05-23 10:59:18 -0700471 case SdkLibraryDependency:
Colin Cross83bb3162018-06-25 15:48:06 -0700472 sdkVersion := j.sdkVersion()
Jiyong Parkc678ad32018-04-10 13:07:10 +0900473 linkType := javaSdk
474 if strings.HasPrefix(sdkVersion, "system_") || strings.HasPrefix(sdkVersion, "test_") {
475 linkType = javaSystem
476 } else if sdkVersion == "" {
477 linkType = javaPlatform
478 }
Sundong Ahn241cd372018-07-13 16:16:44 +0900479 deps.classpath = append(deps.classpath, dep.ImplementationJars(linkType)...)
Colin Cross2d24c1b2018-05-23 10:59:18 -0700480 case android.SourceFileProducer:
Nan Zhang581fd212018-01-10 16:06:12 -0800481 checkProducesJars(ctx, dep)
482 deps.classpath = append(deps.classpath, dep.Srcs()...)
Nan Zhang581fd212018-01-10 16:06:12 -0800483 default:
484 ctx.ModuleErrorf("depends on non-java module %q", otherName)
485 }
Colin Crossa1ce2a02018-06-20 15:19:39 -0700486 case srcsLibTag:
487 switch dep := module.(type) {
488 case Dependency:
489 srcs := dep.(SrcDependency).CompiledSrcs()
490 whitelistPathPrefixes := make(map[string]bool)
491 j.genWhitelistPathPrefixes(whitelistPathPrefixes)
492 for _, src := range srcs {
493 if _, ok := src.(android.WritablePath); ok { // generated sources
494 deps.srcs = append(deps.srcs, src)
495 } else { // select source path for documentation based on whitelist path prefixs.
496 for k, _ := range whitelistPathPrefixes {
497 if strings.HasPrefix(src.Rel(), k) {
498 deps.srcs = append(deps.srcs, src)
499 break
500 }
501 }
502 }
503 }
504 deps.srcJars = append(deps.srcJars, dep.(SrcDependency).CompiledSrcJars()...)
505 default:
506 ctx.ModuleErrorf("depends on non-java module %q", otherName)
507 }
Nan Zhang357466b2018-04-17 17:38:36 -0700508 case systemModulesTag:
509 if deps.systemModules != nil {
510 panic("Found two system module dependencies")
511 }
512 sm := module.(*SystemModules)
513 if sm.outputFile == nil {
514 panic("Missing directory for system module dependency")
515 }
516 deps.systemModules = sm.outputFile
Nan Zhang581fd212018-01-10 16:06:12 -0800517 }
518 })
519 // do not pass exclude_srcs directly when expanding srcFiles since exclude_srcs
520 // may contain filegroup or genrule.
521 srcFiles := ctx.ExpandSources(j.properties.Srcs, j.properties.Exclude_srcs)
Nan Zhanga40da042018-08-01 12:48:00 -0700522 flags := j.collectAidlFlags(ctx, deps)
Jiyong Park1e440682018-05-23 18:42:04 +0900523 srcFiles = j.genSources(ctx, srcFiles, flags)
Nan Zhang581fd212018-01-10 16:06:12 -0800524
525 // srcs may depend on some genrule output.
526 j.srcJars = srcFiles.FilterByExt(".srcjar")
Nan Zhangb2b33de2018-02-23 11:18:47 -0800527 j.srcJars = append(j.srcJars, deps.srcJars...)
528
Nan Zhang581fd212018-01-10 16:06:12 -0800529 j.srcFiles = srcFiles.FilterOutByExt(".srcjar")
Nan Zhangb2b33de2018-02-23 11:18:47 -0800530 j.srcFiles = append(j.srcFiles, deps.srcs...)
Nan Zhang581fd212018-01-10 16:06:12 -0800531
532 j.docZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"docs.zip")
Nan Zhangccff0f72018-03-08 17:26:16 -0800533 j.stubsSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
Nan Zhang581fd212018-01-10 16:06:12 -0800534
535 if j.properties.Local_sourcepaths == nil {
536 j.properties.Local_sourcepaths = append(j.properties.Local_sourcepaths, ".")
537 }
538 j.sourcepaths = android.PathsForModuleSrc(ctx, j.properties.Local_sourcepaths)
Nan Zhang581fd212018-01-10 16:06:12 -0800539
540 return deps
541}
542
543func (j *Javadoc) DepsMutator(ctx android.BottomUpMutatorContext) {
544 j.addDeps(ctx)
545}
546
547func (j *Javadoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
548 deps := j.collectDeps(ctx)
549
550 var implicits android.Paths
551 implicits = append(implicits, deps.bootClasspath...)
552 implicits = append(implicits, deps.classpath...)
553
554 var bootClasspathArgs, classpathArgs string
Nan Zhang357466b2018-04-17 17:38:36 -0700555
Colin Cross83bb3162018-06-25 15:48:06 -0700556 javaVersion := getJavaVersion(ctx, String(j.properties.Java_version), sdkContext(j))
Colin Cross997262f2018-06-19 22:49:39 -0700557 if len(deps.bootClasspath) > 0 {
558 var systemModules classpath
559 if deps.systemModules != nil {
560 systemModules = append(systemModules, deps.systemModules)
Nan Zhang581fd212018-01-10 16:06:12 -0800561 }
Colin Cross997262f2018-06-19 22:49:39 -0700562 bootClasspathArgs = systemModules.FormJavaSystemModulesPath("--system ", ctx.Device())
563 bootClasspathArgs = bootClasspathArgs + " --patch-module java.base=."
Nan Zhang581fd212018-01-10 16:06:12 -0800564 }
565 if len(deps.classpath.Strings()) > 0 {
566 classpathArgs = "-classpath " + strings.Join(deps.classpath.Strings(), ":")
567 }
568
569 implicits = append(implicits, j.srcJars...)
570
Nan Zhangaf322cc2018-06-19 15:15:38 -0700571 opts := "-source " + javaVersion + " -J-Xmx1024m -XDignore.symbol.file -Xdoclint:none"
Nan Zhang581fd212018-01-10 16:06:12 -0800572
573 ctx.Build(pctx, android.BuildParams{
574 Rule: javadoc,
575 Description: "Javadoc",
Nan Zhangccff0f72018-03-08 17:26:16 -0800576 Output: j.stubsSrcJar,
Nan Zhang581fd212018-01-10 16:06:12 -0800577 ImplicitOutput: j.docZip,
578 Inputs: j.srcFiles,
579 Implicits: implicits,
580 Args: map[string]string{
Nan Zhangde860a42018-08-08 16:32:21 -0700581 "outDir": android.PathForModuleOut(ctx, "out").String(),
582 "srcJarDir": android.PathForModuleOut(ctx, "srcjars").String(),
583 "stubsDir": android.PathForModuleOut(ctx, "stubsDir").String(),
Nan Zhang581fd212018-01-10 16:06:12 -0800584 "srcJars": strings.Join(j.srcJars.Strings(), " "),
585 "opts": opts,
Nan Zhang853f4202018-04-12 16:55:56 -0700586 "bootclasspathArgs": bootClasspathArgs,
Nan Zhang581fd212018-01-10 16:06:12 -0800587 "classpathArgs": classpathArgs,
588 "sourcepath": strings.Join(j.sourcepaths.Strings(), ":"),
589 "docZip": j.docZip.String(),
590 },
591 })
592}
593
Nan Zhanga40da042018-08-01 12:48:00 -0700594//
595// Droiddoc
596//
597type Droiddoc struct {
598 Javadoc
599
600 properties DroiddocProperties
601 apiFile android.WritablePath
602 dexApiFile android.WritablePath
603 privateApiFile android.WritablePath
604 privateDexApiFile android.WritablePath
605 removedApiFile android.WritablePath
606 removedDexApiFile android.WritablePath
607 exactApiFile android.WritablePath
608 apiMappingFile android.WritablePath
609
610 checkCurrentApiTimestamp android.WritablePath
611 updateCurrentApiTimestamp android.WritablePath
612 checkLastReleasedApiTimestamp android.WritablePath
613
614 annotationsZip android.WritablePath
615
616 apiFilePath android.Path
617}
618
619type ApiFilePath interface {
620 ApiFilePath() android.Path
621}
622
623func DroiddocFactory() android.Module {
624 module := &Droiddoc{}
625
626 module.AddProperties(&module.properties,
627 &module.Javadoc.properties)
628
629 InitDroiddocModule(module, android.HostAndDeviceSupported)
630 return module
631}
632
633func DroiddocHostFactory() android.Module {
634 module := &Droiddoc{}
635
636 module.AddProperties(&module.properties,
637 &module.Javadoc.properties)
638
639 InitDroiddocModule(module, android.HostSupported)
640 return module
641}
642
643func (d *Droiddoc) ApiFilePath() android.Path {
644 return d.apiFilePath
645}
646
Nan Zhang61819ce2018-05-04 18:49:16 -0700647func (d *Droiddoc) checkCurrentApi() bool {
648 if String(d.properties.Check_api.Current.Api_file) != "" &&
649 String(d.properties.Check_api.Current.Removed_api_file) != "" {
650 return true
651 } else if String(d.properties.Check_api.Current.Api_file) != "" {
652 panic("check_api.current.removed_api_file: has to be non empty!")
653 } else if String(d.properties.Check_api.Current.Removed_api_file) != "" {
654 panic("check_api.current.api_file: has to be non empty!")
655 }
656
657 return false
658}
659
660func (d *Droiddoc) checkLastReleasedApi() bool {
661 if String(d.properties.Check_api.Last_released.Api_file) != "" &&
662 String(d.properties.Check_api.Last_released.Removed_api_file) != "" {
663 return true
664 } else if String(d.properties.Check_api.Last_released.Api_file) != "" {
665 panic("check_api.last_released.removed_api_file: has to be non empty!")
666 } else if String(d.properties.Check_api.Last_released.Removed_api_file) != "" {
667 panic("check_api.last_released.api_file: has to be non empty!")
668 }
669
670 return false
671}
672
Nan Zhang581fd212018-01-10 16:06:12 -0800673func (d *Droiddoc) DepsMutator(ctx android.BottomUpMutatorContext) {
674 d.Javadoc.addDeps(ctx)
675
Nan Zhang79614d12018-04-19 18:03:39 -0700676 if String(d.properties.Custom_template) != "" {
Dan Willemsencc090972018-02-26 14:33:31 -0800677 ctx.AddDependency(ctx.Module(), droiddocTemplateTag, String(d.properties.Custom_template))
678 }
679
Nan Zhanga40da042018-08-01 12:48:00 -0700680 // arg_files may contains filegroup or genrule.
Nan Zhang581fd212018-01-10 16:06:12 -0800681 android.ExtractSourcesDeps(ctx, d.properties.Arg_files)
682
683 // knowntags may contain filegroup or genrule.
684 android.ExtractSourcesDeps(ctx, d.properties.Knowntags)
Nan Zhang61819ce2018-05-04 18:49:16 -0700685
Nan Zhange2ba5d42018-07-11 15:16:55 -0700686 if String(d.properties.Static_doc_index_redirect) != "" {
687 android.ExtractSourceDeps(ctx, d.properties.Static_doc_index_redirect)
688 }
689
690 if String(d.properties.Static_doc_properties) != "" {
691 android.ExtractSourceDeps(ctx, d.properties.Static_doc_properties)
692 }
693
Nan Zhang61819ce2018-05-04 18:49:16 -0700694 if d.checkCurrentApi() {
695 android.ExtractSourceDeps(ctx, d.properties.Check_api.Current.Api_file)
696 android.ExtractSourceDeps(ctx, d.properties.Check_api.Current.Removed_api_file)
697 }
698
699 if d.checkLastReleasedApi() {
700 android.ExtractSourceDeps(ctx, d.properties.Check_api.Last_released.Api_file)
701 android.ExtractSourceDeps(ctx, d.properties.Check_api.Last_released.Removed_api_file)
702 }
Nan Zhang79614d12018-04-19 18:03:39 -0700703
704 if String(d.properties.Metalava_previous_api) != "" {
705 android.ExtractSourceDeps(ctx, d.properties.Metalava_previous_api)
706 }
Nan Zhangf4936b02018-08-01 15:00:28 -0700707
708 if len(d.properties.Metalava_merge_annotations_dirs) != 0 {
709 for _, mergeAnnotationsDir := range d.properties.Metalava_merge_annotations_dirs {
710 ctx.AddDependency(ctx.Module(), metalavaMergeAnnotationsDirTag, mergeAnnotationsDir)
711 }
712 }
Nan Zhang581fd212018-01-10 16:06:12 -0800713}
714
Nan Zhanga40da042018-08-01 12:48:00 -0700715func (d *Droiddoc) initBuilderFlags(ctx android.ModuleContext, implicits *android.Paths, deps deps) (droiddocBuilderFlags, error) {
716 var flags droiddocBuilderFlags
Nan Zhang581fd212018-01-10 16:06:12 -0800717
Nan Zhanga40da042018-08-01 12:48:00 -0700718 *implicits = append(*implicits, deps.bootClasspath...)
719 *implicits = append(*implicits, deps.classpath...)
Nan Zhang581fd212018-01-10 16:06:12 -0800720
Nan Zhangc94f9d82018-06-26 10:02:26 -0700721 // continue to use -bootclasspath even if Metalava under -source 1.9 is enabled
722 // since it doesn't support system modules yet.
723 if len(deps.bootClasspath.Strings()) > 0 {
724 // For OpenJDK 8 we can use -bootclasspath to define the core libraries code.
Nan Zhanga40da042018-08-01 12:48:00 -0700725 flags.bootClasspathArgs = deps.bootClasspath.FormJavaClassPath("-bootclasspath")
Nan Zhang357466b2018-04-17 17:38:36 -0700726 }
Nan Zhanga40da042018-08-01 12:48:00 -0700727 flags.classpathArgs = deps.classpath.FormJavaClassPath("-classpath")
Nan Zhang86d2d552018-08-09 15:33:27 -0700728 // Dokka doesn't support boocClasspath, so combine these two classpath vars for Dokka.
729 dokkaClasspath := classpath{}
730 dokkaClasspath = append(dokkaClasspath, deps.bootClasspath...)
731 dokkaClasspath = append(dokkaClasspath, deps.classpath...)
732 flags.dokkaClasspathArgs = dokkaClasspath.FormJavaClassPath("-classpath")
Nan Zhang79614d12018-04-19 18:03:39 -0700733
Nan Zhang581fd212018-01-10 16:06:12 -0800734 argFiles := ctx.ExpandSources(d.properties.Arg_files, nil)
735 argFilesMap := map[string]android.Path{}
736
737 for _, f := range argFiles {
Nan Zhanga40da042018-08-01 12:48:00 -0700738 *implicits = append(*implicits, f)
Nan Zhang581fd212018-01-10 16:06:12 -0800739 if _, exists := argFilesMap[f.Rel()]; !exists {
740 argFilesMap[f.Rel()] = f
741 } else {
742 ctx.ModuleErrorf("multiple arg_files for %q, %q and %q",
743 f, argFilesMap[f.Rel()], f.Rel())
744 }
745 }
746
Nan Zhanga40da042018-08-01 12:48:00 -0700747 var err error
748 flags.args, err = android.Expand(String(d.properties.Args), func(name string) (string, error) {
Nan Zhang581fd212018-01-10 16:06:12 -0800749 if strings.HasPrefix(name, "location ") {
750 label := strings.TrimSpace(strings.TrimPrefix(name, "location "))
751 if f, ok := argFilesMap[label]; ok {
752 return f.String(), nil
753 } else {
754 return "", fmt.Errorf("unknown location label %q", label)
755 }
756 } else if name == "genDir" {
757 return android.PathForModuleGen(ctx).String(), nil
758 }
759 return "", fmt.Errorf("unknown variable '$(%s)'", name)
760 })
761
762 if err != nil {
Nan Zhang79614d12018-04-19 18:03:39 -0700763 ctx.PropertyErrorf("args", "%s", err.Error())
Nan Zhanga40da042018-08-01 12:48:00 -0700764 return droiddocBuilderFlags{}, err
Nan Zhang581fd212018-01-10 16:06:12 -0800765 }
Nan Zhanga40da042018-08-01 12:48:00 -0700766 return flags, nil
767}
Nan Zhang581fd212018-01-10 16:06:12 -0800768
Nan Zhanga40da042018-08-01 12:48:00 -0700769func (d *Droiddoc) collectDoclavaDocsFlags(ctx android.ModuleContext, implicits *android.Paths,
Nan Zhang443fa522018-08-20 20:58:28 -0700770 jsilver, doclava android.Path) string {
Nan Zhang581fd212018-01-10 16:06:12 -0800771
Nan Zhanga40da042018-08-01 12:48:00 -0700772 *implicits = append(*implicits, jsilver)
773 *implicits = append(*implicits, doclava)
Nan Zhang30963742018-04-23 09:59:14 -0700774
Nan Zhang46130972018-06-04 11:28:01 -0700775 var date string
776 if runtime.GOOS == "darwin" {
777 date = `date -r`
778 } else {
779 date = `date -d`
780 }
781
Nan Zhang443fa522018-08-20 20:58:28 -0700782 // Droiddoc always gets "-source 1.8" because it doesn't support 1.9 sources. For modules with 1.9
783 // sources, droiddoc will get sources produced by metalava which will have already stripped out the
784 // 1.9 language features.
785 args := " -source 1.8 -J-Xmx1600m -J-XX:-OmitStackTraceInFastThrow -XDignore.symbol.file " +
Nan Zhang30963742018-04-23 09:59:14 -0700786 "-doclet com.google.doclava.Doclava -docletpath " + jsilver.String() + ":" + doclava.String() + " " +
Nan Zhang581fd212018-01-10 16:06:12 -0800787 "-hdf page.build " + ctx.Config().BuildId() + "-" + ctx.Config().BuildNumberFromFile() + " " +
Nan Zhang79614d12018-04-19 18:03:39 -0700788 `-hdf page.now "$$(` + date + ` @$$(cat ` + ctx.Config().Getenv("BUILD_DATETIME_FILE") + `) "+%d %b %Y %k:%M")" `
Nan Zhang46130972018-06-04 11:28:01 -0700789
Nan Zhanga40da042018-08-01 12:48:00 -0700790 if String(d.properties.Custom_template) == "" {
791 // TODO: This is almost always droiddoc-templates-sdk
792 ctx.PropertyErrorf("custom_template", "must specify a template")
793 }
794
795 ctx.VisitDirectDepsWithTag(droiddocTemplateTag, func(m android.Module) {
Nan Zhangf4936b02018-08-01 15:00:28 -0700796 if t, ok := m.(*ExportedDroiddocDir); ok {
Nan Zhanga40da042018-08-01 12:48:00 -0700797 *implicits = append(*implicits, t.deps...)
798 args = args + " -templatedir " + t.dir.String()
799 } else {
800 ctx.PropertyErrorf("custom_template", "module %q is not a droiddoc_template", ctx.OtherModuleName(m))
801 }
802 })
803
804 if len(d.properties.Html_dirs) > 0 {
805 htmlDir := android.PathForModuleSrc(ctx, d.properties.Html_dirs[0])
806 *implicits = append(*implicits, ctx.Glob(htmlDir.Join(ctx, "**/*").String(), nil)...)
807 args = args + " -htmldir " + htmlDir.String()
808 }
809
810 if len(d.properties.Html_dirs) > 1 {
811 htmlDir2 := android.PathForModuleSrc(ctx, d.properties.Html_dirs[1])
812 *implicits = append(*implicits, ctx.Glob(htmlDir2.Join(ctx, "**/*").String(), nil)...)
813 args = args + " -htmldir2 " + htmlDir2.String()
814 }
815
816 if len(d.properties.Html_dirs) > 2 {
817 ctx.PropertyErrorf("html_dirs", "Droiddoc only supports up to 2 html dirs")
818 }
819
820 knownTags := ctx.ExpandSources(d.properties.Knowntags, nil)
821 *implicits = append(*implicits, knownTags...)
822
823 for _, kt := range knownTags {
824 args = args + " -knowntags " + kt.String()
825 }
826
827 for _, hdf := range d.properties.Hdf {
828 args = args + " -hdf " + hdf
829 }
830
831 if String(d.properties.Proofread_file) != "" {
832 proofreadFile := android.PathForModuleOut(ctx, String(d.properties.Proofread_file))
833 args = args + " -proofread " + proofreadFile.String()
834 }
835
836 if String(d.properties.Todo_file) != "" {
837 // tricky part:
838 // we should not compute full path for todo_file through PathForModuleOut().
839 // the non-standard doclet will get the full path relative to "-o".
840 args = args + " -todo " + String(d.properties.Todo_file)
841 }
842
843 if String(d.properties.Resourcesdir) != "" {
844 // TODO: should we add files under resourcesDir to the implicits? It seems that
845 // resourcesDir is one sub dir of htmlDir
846 resourcesDir := android.PathForModuleSrc(ctx, String(d.properties.Resourcesdir))
847 args = args + " -resourcesdir " + resourcesDir.String()
848 }
849
850 if String(d.properties.Resourcesoutdir) != "" {
851 // TODO: it seems -resourceoutdir reference/android/images/ didn't get generated anywhere.
852 args = args + " -resourcesoutdir " + String(d.properties.Resourcesoutdir)
853 }
854 return args
855}
856
857func (d *Droiddoc) collectStubsFlags(ctx android.ModuleContext, implicitOutputs *android.WritablePaths) (string, string) {
858 var doclavaFlags, MetalavaFlags string
859 if d.checkCurrentApi() || d.checkLastReleasedApi() || String(d.properties.Api_filename) != "" {
860 d.apiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_api.txt")
861 doclavaFlags += " -api " + d.apiFile.String()
862 MetalavaFlags = MetalavaFlags + " --api " + d.apiFile.String()
863 *implicitOutputs = append(*implicitOutputs, d.apiFile)
864 d.apiFilePath = d.apiFile
865 }
866
867 if d.checkCurrentApi() || d.checkLastReleasedApi() || String(d.properties.Removed_api_filename) != "" {
868 d.removedApiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_removed.txt")
869 doclavaFlags += " -removedApi " + d.removedApiFile.String()
870 MetalavaFlags = MetalavaFlags + " --removed-api " + d.removedApiFile.String()
871 *implicitOutputs = append(*implicitOutputs, d.removedApiFile)
872 }
873
874 if String(d.properties.Private_api_filename) != "" {
875 d.privateApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_api_filename))
876 doclavaFlags += " -privateApi " + d.privateApiFile.String()
877 MetalavaFlags = MetalavaFlags + " --private-api " + d.privateApiFile.String()
878 *implicitOutputs = append(*implicitOutputs, d.privateApiFile)
879 }
880
881 if String(d.properties.Dex_api_filename) != "" {
882 d.dexApiFile = android.PathForModuleOut(ctx, String(d.properties.Dex_api_filename))
883 doclavaFlags += " -dexApi " + d.dexApiFile.String()
884 *implicitOutputs = append(*implicitOutputs, d.dexApiFile)
885 }
886
887 if String(d.properties.Private_dex_api_filename) != "" {
888 d.privateDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_dex_api_filename))
889 doclavaFlags += " -privateDexApi " + d.privateDexApiFile.String()
890 MetalavaFlags = MetalavaFlags + " --private-dex-api " + d.privateDexApiFile.String()
891 *implicitOutputs = append(*implicitOutputs, d.privateDexApiFile)
892 }
893
894 if String(d.properties.Removed_dex_api_filename) != "" {
895 d.removedDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Removed_dex_api_filename))
896 doclavaFlags += " -removedDexApi " + d.removedDexApiFile.String()
897 MetalavaFlags = MetalavaFlags + " --removed-dex-api " + d.removedDexApiFile.String()
898 *implicitOutputs = append(*implicitOutputs, d.removedDexApiFile)
899 }
900
901 if String(d.properties.Exact_api_filename) != "" {
902 d.exactApiFile = android.PathForModuleOut(ctx, String(d.properties.Exact_api_filename))
903 doclavaFlags += " -exactApi " + d.exactApiFile.String()
904 MetalavaFlags = MetalavaFlags + " --exact-api " + d.exactApiFile.String()
905 *implicitOutputs = append(*implicitOutputs, d.exactApiFile)
906 }
907
908 if String(d.properties.Dex_mapping_filename) != "" {
909 d.apiMappingFile = android.PathForModuleOut(ctx, String(d.properties.Dex_mapping_filename))
910 doclavaFlags += " -apiMapping " + d.apiMappingFile.String()
911 // Omitted: metalava support
912 *implicitOutputs = append(*implicitOutputs, d.apiMappingFile)
913 }
914
915 if BoolDefault(d.properties.Create_stubs, true) {
Nan Zhangde860a42018-08-08 16:32:21 -0700916 doclavaFlags += " -stubs " + android.PathForModuleOut(ctx, "stubsDir").String()
Nan Zhanga40da042018-08-01 12:48:00 -0700917 }
918
919 if Bool(d.properties.Write_sdk_values) {
Nan Zhangde860a42018-08-08 16:32:21 -0700920 doclavaFlags += " -sdkvalues " + android.PathForModuleOut(ctx, "out").String()
Nan Zhanga40da042018-08-01 12:48:00 -0700921 }
922 return doclavaFlags, MetalavaFlags
923}
924
925func (d *Droiddoc) getPostDoclavaCmds(ctx android.ModuleContext, implicits *android.Paths) string {
926 var cmds string
927 if String(d.properties.Static_doc_index_redirect) != "" {
928 static_doc_index_redirect := ctx.ExpandSource(String(d.properties.Static_doc_index_redirect),
929 "static_doc_index_redirect")
930 *implicits = append(*implicits, static_doc_index_redirect)
931 cmds = cmds + " && cp " + static_doc_index_redirect.String() + " " +
Nan Zhangde860a42018-08-08 16:32:21 -0700932 android.PathForModuleOut(ctx, "out", "index.html").String()
Nan Zhanga40da042018-08-01 12:48:00 -0700933 }
934
935 if String(d.properties.Static_doc_properties) != "" {
936 static_doc_properties := ctx.ExpandSource(String(d.properties.Static_doc_properties),
937 "static_doc_properties")
938 *implicits = append(*implicits, static_doc_properties)
939 cmds = cmds + " && cp " + static_doc_properties.String() + " " +
Nan Zhangde860a42018-08-08 16:32:21 -0700940 android.PathForModuleOut(ctx, "out", "source.properties").String()
Nan Zhanga40da042018-08-01 12:48:00 -0700941 }
942 return cmds
943}
944
945func (d *Droiddoc) collectMetalavaAnnotationsFlags(
946 ctx android.ModuleContext, implicits *android.Paths, implicitOutputs *android.WritablePaths) string {
947 var flags string
Nan Zhanga40da042018-08-01 12:48:00 -0700948 if Bool(d.properties.Metalava_annotations_enabled) {
949 if String(d.properties.Metalava_previous_api) == "" {
950 ctx.PropertyErrorf("metalava_previous_api",
951 "has to be non-empty if annotations was enabled!")
952 }
Nan Zhangde860a42018-08-08 16:32:21 -0700953 previousApi := ctx.ExpandSource(String(d.properties.Metalava_previous_api),
954 "metalava_previous_api")
955 *implicits = append(*implicits, previousApi)
Nan Zhangde860a42018-08-08 16:32:21 -0700956
Nan Zhangd05a4362018-08-15 13:28:54 -0700957 flags += " --include-annotations --migrate-nullness " + previousApi.String()
Nan Zhanga40da042018-08-01 12:48:00 -0700958
959 d.annotationsZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"_annotations.zip")
960 *implicitOutputs = append(*implicitOutputs, d.annotationsZip)
961
Nan Zhangf4936b02018-08-01 15:00:28 -0700962 flags += " --extract-annotations " + d.annotationsZip.String()
963
Nan Zhanga40da042018-08-01 12:48:00 -0700964 if len(d.properties.Metalava_merge_annotations_dirs) == 0 {
965 ctx.PropertyErrorf("metalava_merge_annotations_dirs",
966 "has to be non-empty if annotations was enabled!")
967 }
Nan Zhangf4936b02018-08-01 15:00:28 -0700968 ctx.VisitDirectDepsWithTag(metalavaMergeAnnotationsDirTag, func(m android.Module) {
969 if t, ok := m.(*ExportedDroiddocDir); ok {
970 *implicits = append(*implicits, t.deps...)
971 flags += " --merge-annotations " + t.dir.String()
972 } else {
973 ctx.PropertyErrorf("metalava_merge_annotations_dirs",
974 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
975 }
976 })
Nan Zhanga40da042018-08-01 12:48:00 -0700977 // TODO(tnorbye): find owners to fix these warnings when annotation was enabled.
978 flags += " --hide HiddenTypedefConstant --hide SuperfluousPrefix --hide AnnotationExtraction "
979 }
980
981 return flags
982}
983
Nan Zhang86d2d552018-08-09 15:33:27 -0700984func (d *Droiddoc) collectMetalavaJavadocFlags(ctx android.ModuleContext,
Nan Zhangde860a42018-08-08 16:32:21 -0700985 bootClasspathArgs, classpathArgs, outDir, docStubsDir string) string {
986 return " --doc-stubs " + docStubsDir +
987 " --write-doc-stubs-source-list " + android.PathForModuleOut(ctx, "doc_stubs.srclist").String() +
Nan Zhanga40da042018-08-01 12:48:00 -0700988 " --generate-documentation ${config.JavadocCmd} -encoding UTF-8 DOC_STUBS_SOURCE_LIST " +
989 bootClasspathArgs + " " + classpathArgs + " " + " -sourcepath " +
Nan Zhangde860a42018-08-08 16:32:21 -0700990 docStubsDir + " -quiet -d " + outDir
Nan Zhanga40da042018-08-01 12:48:00 -0700991}
992
Nan Zhang86d2d552018-08-09 15:33:27 -0700993func (d *Droiddoc) collectMetalavaDokkaFlags(ctx android.ModuleContext, implicits *android.Paths,
994 classpathArgs, outDir, docStubsDir string) string {
995 dokka := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "dokka.jar")
996 *implicits = append(*implicits, dokka)
997
998 return " --doc-stubs " + docStubsDir + " --write-doc-stubs-source-list " +
999 android.PathForModuleOut(ctx, "doc_stubs.srclist").String() +
1000 " --generate-documentation ${config.JavaCmd} -jar " + dokka.String() + " " +
1001 docStubsDir + " " + classpathArgs + " -format dac -dacRoot /reference/kotlin -output " + outDir
1002}
1003
1004func (d *Droiddoc) transformMetalava(ctx android.ModuleContext, implicits android.Paths,
1005 implicitOutputs android.WritablePaths, outDir, docStubsDir, javaVersion,
1006 bootclasspathArgs, classpathArgs, opts string) {
1007 ctx.Build(pctx, android.BuildParams{
1008 Rule: metalava,
1009 Description: "Metalava",
1010 Output: d.Javadoc.stubsSrcJar,
1011 Inputs: d.Javadoc.srcFiles,
1012 Implicits: implicits,
1013 ImplicitOutputs: implicitOutputs,
1014 Args: map[string]string{
1015 "outDir": outDir,
1016 "srcJarDir": android.PathForModuleOut(ctx, "srcjars").String(),
1017 "stubsDir": android.PathForModuleOut(ctx, "stubsDir").String(),
1018 "docStubsDir": docStubsDir,
1019 "srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "),
1020 "javaVersion": javaVersion,
1021 "bootclasspathArgs": bootclasspathArgs,
1022 "classpathArgs": classpathArgs,
1023 "sourcepath": strings.Join(d.Javadoc.sourcepaths.Strings(), ":"),
1024 "docZip": d.Javadoc.docZip.String(),
1025 "opts": opts,
1026 },
1027 })
1028}
1029
1030func (d *Droiddoc) transformDoclava(ctx android.ModuleContext, implicits android.Paths,
1031 implicitOutputs android.WritablePaths, bootclasspathArgs, classpathArgs, opts, postDoclavaCmds string) {
1032 ctx.Build(pctx, android.BuildParams{
1033 Rule: javadoc,
1034 Description: "Doclava",
1035 Output: d.Javadoc.stubsSrcJar,
1036 Inputs: d.Javadoc.srcFiles,
1037 Implicits: implicits,
1038 ImplicitOutputs: implicitOutputs,
1039 Args: map[string]string{
1040 "outDir": android.PathForModuleOut(ctx, "out").String(),
1041 "srcJarDir": android.PathForModuleOut(ctx, "srcjars").String(),
1042 "stubsDir": android.PathForModuleOut(ctx, "stubsDir").String(),
1043 "srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "),
1044 "opts": opts,
1045 "bootclasspathArgs": bootclasspathArgs,
1046 "classpathArgs": classpathArgs,
1047 "sourcepath": strings.Join(d.Javadoc.sourcepaths.Strings(), ":"),
1048 "docZip": d.Javadoc.docZip.String(),
1049 "postDoclavaCmds": postDoclavaCmds,
1050 },
1051 })
1052}
1053
1054func (d *Droiddoc) transformCheckApi(ctx android.ModuleContext, apiFile, removedApiFile android.Path,
1055 checkApiClasspath classpath, msg, opts string, output android.WritablePath) {
1056 ctx.Build(pctx, android.BuildParams{
1057 Rule: apiCheck,
1058 Description: "Check API",
1059 Output: output,
1060 Inputs: nil,
1061 Implicits: append(android.Paths{apiFile, removedApiFile, d.apiFile, d.removedApiFile},
1062 checkApiClasspath...),
1063 Args: map[string]string{
1064 "classpath": checkApiClasspath.FormJavaClassPath(""),
1065 "opts": opts,
1066 "apiFile": apiFile.String(),
1067 "apiFileToCheck": d.apiFile.String(),
1068 "removedApiFile": removedApiFile.String(),
1069 "removedApiFileToCheck": d.removedApiFile.String(),
1070 "msg": msg,
1071 },
1072 })
1073}
1074
1075func (d *Droiddoc) transformUpdateApi(ctx android.ModuleContext, apiFile, removedApiFile android.Path,
1076 output android.WritablePath) {
1077 ctx.Build(pctx, android.BuildParams{
1078 Rule: updateApi,
1079 Description: "Update API",
1080 Output: output,
1081 Implicits: append(android.Paths{}, apiFile, removedApiFile, d.apiFile, d.removedApiFile),
1082 Args: map[string]string{
1083 "apiFile": apiFile.String(),
1084 "apiFileToCheck": d.apiFile.String(),
1085 "removedApiFile": removedApiFile.String(),
1086 "removedApiFileToCheck": d.removedApiFile.String(),
1087 },
1088 })
1089}
1090
Nan Zhanga40da042018-08-01 12:48:00 -07001091func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1092 deps := d.Javadoc.collectDeps(ctx)
1093
1094 javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), sdkContext(d))
Nan Zhanga40da042018-08-01 12:48:00 -07001095 jsilver := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "jsilver.jar")
1096 doclava := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "doclava.jar")
1097 java8Home := ctx.Config().Getenv("ANDROID_JAVA8_HOME")
1098 checkApiClasspath := classpath{jsilver, doclava, android.PathForSource(ctx, java8Home, "lib/tools.jar")}
Nan Zhang581fd212018-01-10 16:06:12 -08001099
Nan Zhanga40da042018-08-01 12:48:00 -07001100 var implicits android.Paths
1101 implicits = append(implicits, d.Javadoc.srcJars...)
1102
1103 var implicitOutputs android.WritablePaths
1104 implicitOutputs = append(implicitOutputs, d.Javadoc.docZip)
1105 for _, o := range d.properties.Out {
1106 implicitOutputs = append(implicitOutputs, android.PathForModuleGen(ctx, o))
1107 }
1108
1109 flags, err := d.initBuilderFlags(ctx, &implicits, deps)
1110 if err != nil {
1111 return
1112 }
1113
1114 flags.doclavaStubsFlags, flags.metalavaStubsFlags = d.collectStubsFlags(ctx, &implicitOutputs)
1115 if Bool(d.properties.Metalava_enabled) {
Nan Zhanga40da042018-08-01 12:48:00 -07001116 flags.metalavaAnnotationsFlags = d.collectMetalavaAnnotationsFlags(ctx, &implicits, &implicitOutputs)
Nan Zhang86d2d552018-08-09 15:33:27 -07001117 outDir := android.PathForModuleOut(ctx, "out").String()
Nan Zhangde860a42018-08-08 16:32:21 -07001118 docStubsDir := android.PathForModuleOut(ctx, "docStubsDir").String()
Nan Zhang86d2d552018-08-09 15:33:27 -07001119 // TODO(nanzhang): Add a Soong property to handle documentation args.
1120 if strings.Contains(flags.args, "--generate-documentation") { // enable docs generation
1121 if Bool(d.properties.Dokka_enabled) {
1122 flags.metalavaDokkaFlags = d.collectMetalavaDokkaFlags(ctx, &implicits,
1123 flags.dokkaClasspathArgs, outDir, docStubsDir)
1124 d.transformMetalava(ctx, implicits, implicitOutputs, outDir, docStubsDir, javaVersion,
1125 flags.bootClasspathArgs, flags.classpathArgs, flags.metalavaStubsFlags+
1126 flags.metalavaAnnotationsFlags+" "+strings.Split(flags.args, "--generate-documentation")[0]+
1127 flags.metalavaDokkaFlags+" "+strings.Split(flags.args, "--generate-documentation")[1])
1128 } else {
1129 flags.metalavaJavadocFlags = d.collectMetalavaJavadocFlags(
1130 ctx, flags.bootClasspathArgs, flags.classpathArgs, outDir, docStubsDir)
Nan Zhang443fa522018-08-20 20:58:28 -07001131 flags.doclavaDocsFlags = d.collectDoclavaDocsFlags(ctx, &implicits, jsilver, doclava)
Nan Zhang86d2d552018-08-09 15:33:27 -07001132 d.transformMetalava(ctx, implicits, implicitOutputs, outDir, docStubsDir, javaVersion,
1133 flags.bootClasspathArgs, flags.classpathArgs, flags.metalavaStubsFlags+
1134 flags.metalavaAnnotationsFlags+" "+strings.Split(flags.args, "--generate-documentation")[0]+
1135 flags.metalavaJavadocFlags+flags.doclavaDocsFlags+
1136 " "+strings.Split(flags.args, "--generate-documentation")[1])
1137 }
Nan Zhanga40da042018-08-01 12:48:00 -07001138 } else {
Nan Zhang86d2d552018-08-09 15:33:27 -07001139 d.transformMetalava(ctx, implicits, implicitOutputs, outDir, docStubsDir, javaVersion,
1140 flags.bootClasspathArgs, flags.classpathArgs,
1141 flags.metalavaStubsFlags+flags.metalavaAnnotationsFlags+flags.args)
Nan Zhang79614d12018-04-19 18:03:39 -07001142 }
Nan Zhanga40da042018-08-01 12:48:00 -07001143 } else {
Nan Zhang443fa522018-08-20 20:58:28 -07001144 flags.doclavaDocsFlags = d.collectDoclavaDocsFlags(ctx, &implicits, jsilver, doclava)
Nan Zhanga40da042018-08-01 12:48:00 -07001145 flags.postDoclavaCmds = d.getPostDoclavaCmds(ctx, &implicits)
Nan Zhang86d2d552018-08-09 15:33:27 -07001146 d.transformDoclava(ctx, implicits, implicitOutputs, flags.bootClasspathArgs, flags.classpathArgs,
1147 flags.doclavaDocsFlags+flags.doclavaStubsFlags+" "+flags.args,
1148 flags.postDoclavaCmds)
Nan Zhang79614d12018-04-19 18:03:39 -07001149 }
Nan Zhang61819ce2018-05-04 18:49:16 -07001150
Nan Zhang61819ce2018-05-04 18:49:16 -07001151 if d.checkCurrentApi() && !ctx.Config().IsPdkBuild() {
Nan Zhang61819ce2018-05-04 18:49:16 -07001152 apiFile := ctx.ExpandSource(String(d.properties.Check_api.Current.Api_file),
1153 "check_api.current.api_file")
1154 removedApiFile := ctx.ExpandSource(String(d.properties.Check_api.Current.Removed_api_file),
1155 "check_api.current_removed_api_file")
1156
Nan Zhang55e0bf42018-08-16 16:23:11 -07001157 if !Bool(d.properties.Metalava_enabled) {
1158 d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, "check_current_api.timestamp")
1159 d.transformCheckApi(ctx, apiFile, removedApiFile, checkApiClasspath,
1160 fmt.Sprintf(`\n******************************\n`+
1161 `You have tried to change the API from what has been previously approved.\n\n`+
1162 `To make these errors go away, you have two choices:\n`+
1163 ` 1. You can add '@hide' javadoc comments to the methods, etc. listed in the\n`+
1164 ` errors above.\n\n`+
1165 ` 2. You can update current.txt by executing the following command:\n`+
1166 ` make %s-update-current-api\n\n`+
1167 ` To submit the revised current.txt to the main Android repository,\n`+
1168 ` you will need approval.\n`+
1169 `******************************\n`, ctx.ModuleName()), String(d.properties.Check_api.Current.Args),
1170 d.checkCurrentApiTimestamp)
1171 } else {
1172 // TODO(nanzhang): Refactor below when Metalava support API check.
1173 if d.apiFile == nil || d.removedApiFile == nil {
1174 ctx.ModuleErrorf("api_filename and removed_api_filename properties cannot be empty for API check!")
1175 }
1176 }
Nan Zhang61819ce2018-05-04 18:49:16 -07001177
1178 d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, "update_current_api.timestamp")
Nan Zhang86d2d552018-08-09 15:33:27 -07001179 d.transformUpdateApi(ctx, apiFile, removedApiFile, d.updateCurrentApiTimestamp)
Nan Zhang61819ce2018-05-04 18:49:16 -07001180 }
Nan Zhanga40da042018-08-01 12:48:00 -07001181
Nan Zhang61819ce2018-05-04 18:49:16 -07001182 if d.checkLastReleasedApi() && !ctx.Config().IsPdkBuild() {
1183 d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, "check_last_released_api.timestamp")
1184
1185 apiFile := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Api_file),
1186 "check_api.last_released.api_file")
1187 removedApiFile := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Removed_api_file),
1188 "check_api.last_released.removed_api_file")
1189
Nan Zhang86d2d552018-08-09 15:33:27 -07001190 d.transformCheckApi(ctx, apiFile, removedApiFile, checkApiClasspath,
1191 `\n******************************\n`+
1192 `You have tried to change the API from what has been previously released in\n`+
1193 `an SDK. Please fix the errors listed above.\n`+
1194 `******************************\n`, String(d.properties.Check_api.Last_released.Args),
1195 d.checkLastReleasedApiTimestamp)
Nan Zhang61819ce2018-05-04 18:49:16 -07001196 }
Nan Zhang581fd212018-01-10 16:06:12 -08001197}
Dan Willemsencc090972018-02-26 14:33:31 -08001198
Nan Zhanga40da042018-08-01 12:48:00 -07001199//
Nan Zhangf4936b02018-08-01 15:00:28 -07001200// Exported Droiddoc Directory
Nan Zhanga40da042018-08-01 12:48:00 -07001201//
Dan Willemsencc090972018-02-26 14:33:31 -08001202var droiddocTemplateTag = dependencyTag{name: "droiddoc-template"}
Nan Zhangf4936b02018-08-01 15:00:28 -07001203var metalavaMergeAnnotationsDirTag = dependencyTag{name: "metalava-merge-annotations-dir"}
Dan Willemsencc090972018-02-26 14:33:31 -08001204
Nan Zhangf4936b02018-08-01 15:00:28 -07001205type ExportedDroiddocDirProperties struct {
1206 // path to the directory containing Droiddoc related files.
Dan Willemsencc090972018-02-26 14:33:31 -08001207 Path *string
1208}
1209
Nan Zhangf4936b02018-08-01 15:00:28 -07001210type ExportedDroiddocDir struct {
Dan Willemsencc090972018-02-26 14:33:31 -08001211 android.ModuleBase
1212
Nan Zhangf4936b02018-08-01 15:00:28 -07001213 properties ExportedDroiddocDirProperties
Dan Willemsencc090972018-02-26 14:33:31 -08001214
1215 deps android.Paths
1216 dir android.Path
1217}
1218
Nan Zhangf4936b02018-08-01 15:00:28 -07001219func ExportedDroiddocDirFactory() android.Module {
1220 module := &ExportedDroiddocDir{}
Dan Willemsencc090972018-02-26 14:33:31 -08001221 module.AddProperties(&module.properties)
1222 android.InitAndroidModule(module)
1223 return module
1224}
1225
Nan Zhangf4936b02018-08-01 15:00:28 -07001226func (d *ExportedDroiddocDir) DepsMutator(android.BottomUpMutatorContext) {}
Dan Willemsencc090972018-02-26 14:33:31 -08001227
Nan Zhangf4936b02018-08-01 15:00:28 -07001228func (d *ExportedDroiddocDir) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Dan Willemsencc090972018-02-26 14:33:31 -08001229 path := android.PathForModuleSrc(ctx, String(d.properties.Path))
1230 d.dir = path
1231 d.deps = ctx.Glob(path.Join(ctx, "**/*").String(), nil)
1232}
Nan Zhangb2b33de2018-02-23 11:18:47 -08001233
1234//
1235// Defaults
1236//
1237type DocDefaults struct {
1238 android.ModuleBase
1239 android.DefaultsModuleBase
1240}
1241
1242func (*DocDefaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1243}
1244
1245func (d *DocDefaults) DepsMutator(ctx android.BottomUpMutatorContext) {
1246}
1247
1248func DocDefaultsFactory() android.Module {
1249 module := &DocDefaults{}
1250
1251 module.AddProperties(
1252 &JavadocProperties{},
1253 &DroiddocProperties{},
1254 )
1255
1256 android.InitDefaultsModule(module)
1257
1258 return module
1259}