blob: f90c548f554fb778991d09856aeefb93b60bfed8 [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,
770 javaVersion string, 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 Zhanga40da042018-08-01 12:48:00 -0700782 args := " -source " + javaVersion + " -J-Xmx1600m -J-XX:-OmitStackTraceInFastThrow -XDignore.symbol.file " +
Nan Zhang30963742018-04-23 09:59:14 -0700783 "-doclet com.google.doclava.Doclava -docletpath " + jsilver.String() + ":" + doclava.String() + " " +
Nan Zhang581fd212018-01-10 16:06:12 -0800784 "-hdf page.build " + ctx.Config().BuildId() + "-" + ctx.Config().BuildNumberFromFile() + " " +
Nan Zhang79614d12018-04-19 18:03:39 -0700785 `-hdf page.now "$$(` + date + ` @$$(cat ` + ctx.Config().Getenv("BUILD_DATETIME_FILE") + `) "+%d %b %Y %k:%M")" `
Nan Zhang46130972018-06-04 11:28:01 -0700786
Nan Zhanga40da042018-08-01 12:48:00 -0700787 if String(d.properties.Custom_template) == "" {
788 // TODO: This is almost always droiddoc-templates-sdk
789 ctx.PropertyErrorf("custom_template", "must specify a template")
790 }
791
792 ctx.VisitDirectDepsWithTag(droiddocTemplateTag, func(m android.Module) {
Nan Zhangf4936b02018-08-01 15:00:28 -0700793 if t, ok := m.(*ExportedDroiddocDir); ok {
Nan Zhanga40da042018-08-01 12:48:00 -0700794 *implicits = append(*implicits, t.deps...)
795 args = args + " -templatedir " + t.dir.String()
796 } else {
797 ctx.PropertyErrorf("custom_template", "module %q is not a droiddoc_template", ctx.OtherModuleName(m))
798 }
799 })
800
801 if len(d.properties.Html_dirs) > 0 {
802 htmlDir := android.PathForModuleSrc(ctx, d.properties.Html_dirs[0])
803 *implicits = append(*implicits, ctx.Glob(htmlDir.Join(ctx, "**/*").String(), nil)...)
804 args = args + " -htmldir " + htmlDir.String()
805 }
806
807 if len(d.properties.Html_dirs) > 1 {
808 htmlDir2 := android.PathForModuleSrc(ctx, d.properties.Html_dirs[1])
809 *implicits = append(*implicits, ctx.Glob(htmlDir2.Join(ctx, "**/*").String(), nil)...)
810 args = args + " -htmldir2 " + htmlDir2.String()
811 }
812
813 if len(d.properties.Html_dirs) > 2 {
814 ctx.PropertyErrorf("html_dirs", "Droiddoc only supports up to 2 html dirs")
815 }
816
817 knownTags := ctx.ExpandSources(d.properties.Knowntags, nil)
818 *implicits = append(*implicits, knownTags...)
819
820 for _, kt := range knownTags {
821 args = args + " -knowntags " + kt.String()
822 }
823
824 for _, hdf := range d.properties.Hdf {
825 args = args + " -hdf " + hdf
826 }
827
828 if String(d.properties.Proofread_file) != "" {
829 proofreadFile := android.PathForModuleOut(ctx, String(d.properties.Proofread_file))
830 args = args + " -proofread " + proofreadFile.String()
831 }
832
833 if String(d.properties.Todo_file) != "" {
834 // tricky part:
835 // we should not compute full path for todo_file through PathForModuleOut().
836 // the non-standard doclet will get the full path relative to "-o".
837 args = args + " -todo " + String(d.properties.Todo_file)
838 }
839
840 if String(d.properties.Resourcesdir) != "" {
841 // TODO: should we add files under resourcesDir to the implicits? It seems that
842 // resourcesDir is one sub dir of htmlDir
843 resourcesDir := android.PathForModuleSrc(ctx, String(d.properties.Resourcesdir))
844 args = args + " -resourcesdir " + resourcesDir.String()
845 }
846
847 if String(d.properties.Resourcesoutdir) != "" {
848 // TODO: it seems -resourceoutdir reference/android/images/ didn't get generated anywhere.
849 args = args + " -resourcesoutdir " + String(d.properties.Resourcesoutdir)
850 }
851 return args
852}
853
854func (d *Droiddoc) collectStubsFlags(ctx android.ModuleContext, implicitOutputs *android.WritablePaths) (string, string) {
855 var doclavaFlags, MetalavaFlags string
856 if d.checkCurrentApi() || d.checkLastReleasedApi() || String(d.properties.Api_filename) != "" {
857 d.apiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_api.txt")
858 doclavaFlags += " -api " + d.apiFile.String()
859 MetalavaFlags = MetalavaFlags + " --api " + d.apiFile.String()
860 *implicitOutputs = append(*implicitOutputs, d.apiFile)
861 d.apiFilePath = d.apiFile
862 }
863
864 if d.checkCurrentApi() || d.checkLastReleasedApi() || String(d.properties.Removed_api_filename) != "" {
865 d.removedApiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_removed.txt")
866 doclavaFlags += " -removedApi " + d.removedApiFile.String()
867 MetalavaFlags = MetalavaFlags + " --removed-api " + d.removedApiFile.String()
868 *implicitOutputs = append(*implicitOutputs, d.removedApiFile)
869 }
870
871 if String(d.properties.Private_api_filename) != "" {
872 d.privateApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_api_filename))
873 doclavaFlags += " -privateApi " + d.privateApiFile.String()
874 MetalavaFlags = MetalavaFlags + " --private-api " + d.privateApiFile.String()
875 *implicitOutputs = append(*implicitOutputs, d.privateApiFile)
876 }
877
878 if String(d.properties.Dex_api_filename) != "" {
879 d.dexApiFile = android.PathForModuleOut(ctx, String(d.properties.Dex_api_filename))
880 doclavaFlags += " -dexApi " + d.dexApiFile.String()
881 *implicitOutputs = append(*implicitOutputs, d.dexApiFile)
882 }
883
884 if String(d.properties.Private_dex_api_filename) != "" {
885 d.privateDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_dex_api_filename))
886 doclavaFlags += " -privateDexApi " + d.privateDexApiFile.String()
887 MetalavaFlags = MetalavaFlags + " --private-dex-api " + d.privateDexApiFile.String()
888 *implicitOutputs = append(*implicitOutputs, d.privateDexApiFile)
889 }
890
891 if String(d.properties.Removed_dex_api_filename) != "" {
892 d.removedDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Removed_dex_api_filename))
893 doclavaFlags += " -removedDexApi " + d.removedDexApiFile.String()
894 MetalavaFlags = MetalavaFlags + " --removed-dex-api " + d.removedDexApiFile.String()
895 *implicitOutputs = append(*implicitOutputs, d.removedDexApiFile)
896 }
897
898 if String(d.properties.Exact_api_filename) != "" {
899 d.exactApiFile = android.PathForModuleOut(ctx, String(d.properties.Exact_api_filename))
900 doclavaFlags += " -exactApi " + d.exactApiFile.String()
901 MetalavaFlags = MetalavaFlags + " --exact-api " + d.exactApiFile.String()
902 *implicitOutputs = append(*implicitOutputs, d.exactApiFile)
903 }
904
905 if String(d.properties.Dex_mapping_filename) != "" {
906 d.apiMappingFile = android.PathForModuleOut(ctx, String(d.properties.Dex_mapping_filename))
907 doclavaFlags += " -apiMapping " + d.apiMappingFile.String()
908 // Omitted: metalava support
909 *implicitOutputs = append(*implicitOutputs, d.apiMappingFile)
910 }
911
912 if BoolDefault(d.properties.Create_stubs, true) {
Nan Zhangde860a42018-08-08 16:32:21 -0700913 doclavaFlags += " -stubs " + android.PathForModuleOut(ctx, "stubsDir").String()
Nan Zhanga40da042018-08-01 12:48:00 -0700914 }
915
916 if Bool(d.properties.Write_sdk_values) {
Nan Zhangde860a42018-08-08 16:32:21 -0700917 doclavaFlags += " -sdkvalues " + android.PathForModuleOut(ctx, "out").String()
Nan Zhanga40da042018-08-01 12:48:00 -0700918 }
919 return doclavaFlags, MetalavaFlags
920}
921
922func (d *Droiddoc) getPostDoclavaCmds(ctx android.ModuleContext, implicits *android.Paths) string {
923 var cmds string
924 if String(d.properties.Static_doc_index_redirect) != "" {
925 static_doc_index_redirect := ctx.ExpandSource(String(d.properties.Static_doc_index_redirect),
926 "static_doc_index_redirect")
927 *implicits = append(*implicits, static_doc_index_redirect)
928 cmds = cmds + " && cp " + static_doc_index_redirect.String() + " " +
Nan Zhangde860a42018-08-08 16:32:21 -0700929 android.PathForModuleOut(ctx, "out", "index.html").String()
Nan Zhanga40da042018-08-01 12:48:00 -0700930 }
931
932 if String(d.properties.Static_doc_properties) != "" {
933 static_doc_properties := ctx.ExpandSource(String(d.properties.Static_doc_properties),
934 "static_doc_properties")
935 *implicits = append(*implicits, static_doc_properties)
936 cmds = cmds + " && cp " + static_doc_properties.String() + " " +
Nan Zhangde860a42018-08-08 16:32:21 -0700937 android.PathForModuleOut(ctx, "out", "source.properties").String()
Nan Zhanga40da042018-08-01 12:48:00 -0700938 }
939 return cmds
940}
941
942func (d *Droiddoc) collectMetalavaAnnotationsFlags(
943 ctx android.ModuleContext, implicits *android.Paths, implicitOutputs *android.WritablePaths) string {
944 var flags string
Nan Zhanga40da042018-08-01 12:48:00 -0700945 if Bool(d.properties.Metalava_annotations_enabled) {
946 if String(d.properties.Metalava_previous_api) == "" {
947 ctx.PropertyErrorf("metalava_previous_api",
948 "has to be non-empty if annotations was enabled!")
949 }
Nan Zhangde860a42018-08-08 16:32:21 -0700950 previousApi := ctx.ExpandSource(String(d.properties.Metalava_previous_api),
951 "metalava_previous_api")
952 *implicits = append(*implicits, previousApi)
953 flags += " --previous-api " + previousApi.String()
954
Nan Zhanga40da042018-08-01 12:48:00 -0700955 flags += " --include-annotations --migrate-nullness"
956
957 d.annotationsZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"_annotations.zip")
958 *implicitOutputs = append(*implicitOutputs, d.annotationsZip)
959
Nan Zhangf4936b02018-08-01 15:00:28 -0700960 flags += " --extract-annotations " + d.annotationsZip.String()
961
Nan Zhanga40da042018-08-01 12:48:00 -0700962 if len(d.properties.Metalava_merge_annotations_dirs) == 0 {
963 ctx.PropertyErrorf("metalava_merge_annotations_dirs",
964 "has to be non-empty if annotations was enabled!")
965 }
Nan Zhangf4936b02018-08-01 15:00:28 -0700966 ctx.VisitDirectDepsWithTag(metalavaMergeAnnotationsDirTag, func(m android.Module) {
967 if t, ok := m.(*ExportedDroiddocDir); ok {
968 *implicits = append(*implicits, t.deps...)
969 flags += " --merge-annotations " + t.dir.String()
970 } else {
971 ctx.PropertyErrorf("metalava_merge_annotations_dirs",
972 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
973 }
974 })
Nan Zhanga40da042018-08-01 12:48:00 -0700975 // TODO(tnorbye): find owners to fix these warnings when annotation was enabled.
976 flags += " --hide HiddenTypedefConstant --hide SuperfluousPrefix --hide AnnotationExtraction "
977 }
978
979 return flags
980}
981
Nan Zhang86d2d552018-08-09 15:33:27 -0700982func (d *Droiddoc) collectMetalavaJavadocFlags(ctx android.ModuleContext,
Nan Zhangde860a42018-08-08 16:32:21 -0700983 bootClasspathArgs, classpathArgs, outDir, docStubsDir string) string {
984 return " --doc-stubs " + docStubsDir +
985 " --write-doc-stubs-source-list " + android.PathForModuleOut(ctx, "doc_stubs.srclist").String() +
Nan Zhanga40da042018-08-01 12:48:00 -0700986 " --generate-documentation ${config.JavadocCmd} -encoding UTF-8 DOC_STUBS_SOURCE_LIST " +
987 bootClasspathArgs + " " + classpathArgs + " " + " -sourcepath " +
Nan Zhangde860a42018-08-08 16:32:21 -0700988 docStubsDir + " -quiet -d " + outDir
Nan Zhanga40da042018-08-01 12:48:00 -0700989}
990
Nan Zhang86d2d552018-08-09 15:33:27 -0700991func (d *Droiddoc) collectMetalavaDokkaFlags(ctx android.ModuleContext, implicits *android.Paths,
992 classpathArgs, outDir, docStubsDir string) string {
993 dokka := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "dokka.jar")
994 *implicits = append(*implicits, dokka)
995
996 return " --doc-stubs " + docStubsDir + " --write-doc-stubs-source-list " +
997 android.PathForModuleOut(ctx, "doc_stubs.srclist").String() +
998 " --generate-documentation ${config.JavaCmd} -jar " + dokka.String() + " " +
999 docStubsDir + " " + classpathArgs + " -format dac -dacRoot /reference/kotlin -output " + outDir
1000}
1001
1002func (d *Droiddoc) transformMetalava(ctx android.ModuleContext, implicits android.Paths,
1003 implicitOutputs android.WritablePaths, outDir, docStubsDir, javaVersion,
1004 bootclasspathArgs, classpathArgs, opts string) {
1005 ctx.Build(pctx, android.BuildParams{
1006 Rule: metalava,
1007 Description: "Metalava",
1008 Output: d.Javadoc.stubsSrcJar,
1009 Inputs: d.Javadoc.srcFiles,
1010 Implicits: implicits,
1011 ImplicitOutputs: implicitOutputs,
1012 Args: map[string]string{
1013 "outDir": outDir,
1014 "srcJarDir": android.PathForModuleOut(ctx, "srcjars").String(),
1015 "stubsDir": android.PathForModuleOut(ctx, "stubsDir").String(),
1016 "docStubsDir": docStubsDir,
1017 "srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "),
1018 "javaVersion": javaVersion,
1019 "bootclasspathArgs": bootclasspathArgs,
1020 "classpathArgs": classpathArgs,
1021 "sourcepath": strings.Join(d.Javadoc.sourcepaths.Strings(), ":"),
1022 "docZip": d.Javadoc.docZip.String(),
1023 "opts": opts,
1024 },
1025 })
1026}
1027
1028func (d *Droiddoc) transformDoclava(ctx android.ModuleContext, implicits android.Paths,
1029 implicitOutputs android.WritablePaths, bootclasspathArgs, classpathArgs, opts, postDoclavaCmds string) {
1030 ctx.Build(pctx, android.BuildParams{
1031 Rule: javadoc,
1032 Description: "Doclava",
1033 Output: d.Javadoc.stubsSrcJar,
1034 Inputs: d.Javadoc.srcFiles,
1035 Implicits: implicits,
1036 ImplicitOutputs: implicitOutputs,
1037 Args: map[string]string{
1038 "outDir": android.PathForModuleOut(ctx, "out").String(),
1039 "srcJarDir": android.PathForModuleOut(ctx, "srcjars").String(),
1040 "stubsDir": android.PathForModuleOut(ctx, "stubsDir").String(),
1041 "srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "),
1042 "opts": opts,
1043 "bootclasspathArgs": bootclasspathArgs,
1044 "classpathArgs": classpathArgs,
1045 "sourcepath": strings.Join(d.Javadoc.sourcepaths.Strings(), ":"),
1046 "docZip": d.Javadoc.docZip.String(),
1047 "postDoclavaCmds": postDoclavaCmds,
1048 },
1049 })
1050}
1051
1052func (d *Droiddoc) transformCheckApi(ctx android.ModuleContext, apiFile, removedApiFile android.Path,
1053 checkApiClasspath classpath, msg, opts string, output android.WritablePath) {
1054 ctx.Build(pctx, android.BuildParams{
1055 Rule: apiCheck,
1056 Description: "Check API",
1057 Output: output,
1058 Inputs: nil,
1059 Implicits: append(android.Paths{apiFile, removedApiFile, d.apiFile, d.removedApiFile},
1060 checkApiClasspath...),
1061 Args: map[string]string{
1062 "classpath": checkApiClasspath.FormJavaClassPath(""),
1063 "opts": opts,
1064 "apiFile": apiFile.String(),
1065 "apiFileToCheck": d.apiFile.String(),
1066 "removedApiFile": removedApiFile.String(),
1067 "removedApiFileToCheck": d.removedApiFile.String(),
1068 "msg": msg,
1069 },
1070 })
1071}
1072
1073func (d *Droiddoc) transformUpdateApi(ctx android.ModuleContext, apiFile, removedApiFile android.Path,
1074 output android.WritablePath) {
1075 ctx.Build(pctx, android.BuildParams{
1076 Rule: updateApi,
1077 Description: "Update API",
1078 Output: output,
1079 Implicits: append(android.Paths{}, apiFile, removedApiFile, d.apiFile, d.removedApiFile),
1080 Args: map[string]string{
1081 "apiFile": apiFile.String(),
1082 "apiFileToCheck": d.apiFile.String(),
1083 "removedApiFile": removedApiFile.String(),
1084 "removedApiFileToCheck": d.removedApiFile.String(),
1085 },
1086 })
1087}
1088
Nan Zhanga40da042018-08-01 12:48:00 -07001089func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1090 deps := d.Javadoc.collectDeps(ctx)
1091
1092 javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), sdkContext(d))
1093 // Doclava has problem with "-source 1.9", so override javaVersion when Doclava
1094 // is running with EXPERIMENTAL_USE_OPENJDK9=true. And eventually Doclava will be
1095 // replaced by Metalava.
Nan Zhang79614d12018-04-19 18:03:39 -07001096 if !Bool(d.properties.Metalava_enabled) {
Nan Zhanga40da042018-08-01 12:48:00 -07001097 javaVersion = "1.8"
1098 }
Nan Zhang581fd212018-01-10 16:06:12 -08001099
Nan Zhanga40da042018-08-01 12:48:00 -07001100 jsilver := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "jsilver.jar")
1101 doclava := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "doclava.jar")
1102 java8Home := ctx.Config().Getenv("ANDROID_JAVA8_HOME")
1103 checkApiClasspath := classpath{jsilver, doclava, android.PathForSource(ctx, java8Home, "lib/tools.jar")}
Nan Zhang581fd212018-01-10 16:06:12 -08001104
Nan Zhanga40da042018-08-01 12:48:00 -07001105 var implicits android.Paths
1106 implicits = append(implicits, d.Javadoc.srcJars...)
1107
1108 var implicitOutputs android.WritablePaths
1109 implicitOutputs = append(implicitOutputs, d.Javadoc.docZip)
1110 for _, o := range d.properties.Out {
1111 implicitOutputs = append(implicitOutputs, android.PathForModuleGen(ctx, o))
1112 }
1113
1114 flags, err := d.initBuilderFlags(ctx, &implicits, deps)
1115 if err != nil {
1116 return
1117 }
1118
1119 flags.doclavaStubsFlags, flags.metalavaStubsFlags = d.collectStubsFlags(ctx, &implicitOutputs)
1120 if Bool(d.properties.Metalava_enabled) {
Nan Zhanga40da042018-08-01 12:48:00 -07001121 flags.metalavaAnnotationsFlags = d.collectMetalavaAnnotationsFlags(ctx, &implicits, &implicitOutputs)
Nan Zhang86d2d552018-08-09 15:33:27 -07001122 outDir := android.PathForModuleOut(ctx, "out").String()
Nan Zhangde860a42018-08-08 16:32:21 -07001123 docStubsDir := android.PathForModuleOut(ctx, "docStubsDir").String()
Nan Zhang86d2d552018-08-09 15:33:27 -07001124 // TODO(nanzhang): Add a Soong property to handle documentation args.
1125 if strings.Contains(flags.args, "--generate-documentation") { // enable docs generation
1126 if Bool(d.properties.Dokka_enabled) {
1127 flags.metalavaDokkaFlags = d.collectMetalavaDokkaFlags(ctx, &implicits,
1128 flags.dokkaClasspathArgs, outDir, docStubsDir)
1129 d.transformMetalava(ctx, implicits, implicitOutputs, outDir, docStubsDir, javaVersion,
1130 flags.bootClasspathArgs, flags.classpathArgs, flags.metalavaStubsFlags+
1131 flags.metalavaAnnotationsFlags+" "+strings.Split(flags.args, "--generate-documentation")[0]+
1132 flags.metalavaDokkaFlags+" "+strings.Split(flags.args, "--generate-documentation")[1])
1133 } else {
1134 flags.metalavaJavadocFlags = d.collectMetalavaJavadocFlags(
1135 ctx, flags.bootClasspathArgs, flags.classpathArgs, outDir, docStubsDir)
1136 flags.doclavaDocsFlags = d.collectDoclavaDocsFlags(ctx, &implicits, javaVersion, jsilver, doclava)
1137 d.transformMetalava(ctx, implicits, implicitOutputs, outDir, docStubsDir, javaVersion,
1138 flags.bootClasspathArgs, flags.classpathArgs, flags.metalavaStubsFlags+
1139 flags.metalavaAnnotationsFlags+" "+strings.Split(flags.args, "--generate-documentation")[0]+
1140 flags.metalavaJavadocFlags+flags.doclavaDocsFlags+
1141 " "+strings.Split(flags.args, "--generate-documentation")[1])
1142 }
Nan Zhanga40da042018-08-01 12:48:00 -07001143 } else {
Nan Zhang86d2d552018-08-09 15:33:27 -07001144 d.transformMetalava(ctx, implicits, implicitOutputs, outDir, docStubsDir, javaVersion,
1145 flags.bootClasspathArgs, flags.classpathArgs,
1146 flags.metalavaStubsFlags+flags.metalavaAnnotationsFlags+flags.args)
Nan Zhang79614d12018-04-19 18:03:39 -07001147 }
Nan Zhanga40da042018-08-01 12:48:00 -07001148 } else {
1149 flags.doclavaDocsFlags = d.collectDoclavaDocsFlags(ctx, &implicits, javaVersion, jsilver, doclava)
1150 flags.postDoclavaCmds = d.getPostDoclavaCmds(ctx, &implicits)
Nan Zhang86d2d552018-08-09 15:33:27 -07001151 d.transformDoclava(ctx, implicits, implicitOutputs, flags.bootClasspathArgs, flags.classpathArgs,
1152 flags.doclavaDocsFlags+flags.doclavaStubsFlags+" "+flags.args,
1153 flags.postDoclavaCmds)
Nan Zhang79614d12018-04-19 18:03:39 -07001154 }
Nan Zhang61819ce2018-05-04 18:49:16 -07001155
Nan Zhang61819ce2018-05-04 18:49:16 -07001156 if d.checkCurrentApi() && !ctx.Config().IsPdkBuild() {
Nan Zhang61819ce2018-05-04 18:49:16 -07001157 apiFile := ctx.ExpandSource(String(d.properties.Check_api.Current.Api_file),
1158 "check_api.current.api_file")
1159 removedApiFile := ctx.ExpandSource(String(d.properties.Check_api.Current.Removed_api_file),
1160 "check_api.current_removed_api_file")
1161
Nan Zhang55e0bf42018-08-16 16:23:11 -07001162 if !Bool(d.properties.Metalava_enabled) {
1163 d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, "check_current_api.timestamp")
1164 d.transformCheckApi(ctx, apiFile, removedApiFile, checkApiClasspath,
1165 fmt.Sprintf(`\n******************************\n`+
1166 `You have tried to change the API from what has been previously approved.\n\n`+
1167 `To make these errors go away, you have two choices:\n`+
1168 ` 1. You can add '@hide' javadoc comments to the methods, etc. listed in the\n`+
1169 ` errors above.\n\n`+
1170 ` 2. You can update current.txt by executing the following command:\n`+
1171 ` make %s-update-current-api\n\n`+
1172 ` To submit the revised current.txt to the main Android repository,\n`+
1173 ` you will need approval.\n`+
1174 `******************************\n`, ctx.ModuleName()), String(d.properties.Check_api.Current.Args),
1175 d.checkCurrentApiTimestamp)
1176 } else {
1177 // TODO(nanzhang): Refactor below when Metalava support API check.
1178 if d.apiFile == nil || d.removedApiFile == nil {
1179 ctx.ModuleErrorf("api_filename and removed_api_filename properties cannot be empty for API check!")
1180 }
1181 }
Nan Zhang61819ce2018-05-04 18:49:16 -07001182
1183 d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, "update_current_api.timestamp")
Nan Zhang86d2d552018-08-09 15:33:27 -07001184 d.transformUpdateApi(ctx, apiFile, removedApiFile, d.updateCurrentApiTimestamp)
Nan Zhang61819ce2018-05-04 18:49:16 -07001185 }
Nan Zhanga40da042018-08-01 12:48:00 -07001186
Nan Zhang61819ce2018-05-04 18:49:16 -07001187 if d.checkLastReleasedApi() && !ctx.Config().IsPdkBuild() {
1188 d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, "check_last_released_api.timestamp")
1189
1190 apiFile := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Api_file),
1191 "check_api.last_released.api_file")
1192 removedApiFile := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Removed_api_file),
1193 "check_api.last_released.removed_api_file")
1194
Nan Zhang86d2d552018-08-09 15:33:27 -07001195 d.transformCheckApi(ctx, apiFile, removedApiFile, checkApiClasspath,
1196 `\n******************************\n`+
1197 `You have tried to change the API from what has been previously released in\n`+
1198 `an SDK. Please fix the errors listed above.\n`+
1199 `******************************\n`, String(d.properties.Check_api.Last_released.Args),
1200 d.checkLastReleasedApiTimestamp)
Nan Zhang61819ce2018-05-04 18:49:16 -07001201 }
Nan Zhang581fd212018-01-10 16:06:12 -08001202}
Dan Willemsencc090972018-02-26 14:33:31 -08001203
Nan Zhanga40da042018-08-01 12:48:00 -07001204//
Nan Zhangf4936b02018-08-01 15:00:28 -07001205// Exported Droiddoc Directory
Nan Zhanga40da042018-08-01 12:48:00 -07001206//
Dan Willemsencc090972018-02-26 14:33:31 -08001207var droiddocTemplateTag = dependencyTag{name: "droiddoc-template"}
Nan Zhangf4936b02018-08-01 15:00:28 -07001208var metalavaMergeAnnotationsDirTag = dependencyTag{name: "metalava-merge-annotations-dir"}
Dan Willemsencc090972018-02-26 14:33:31 -08001209
Nan Zhangf4936b02018-08-01 15:00:28 -07001210type ExportedDroiddocDirProperties struct {
1211 // path to the directory containing Droiddoc related files.
Dan Willemsencc090972018-02-26 14:33:31 -08001212 Path *string
1213}
1214
Nan Zhangf4936b02018-08-01 15:00:28 -07001215type ExportedDroiddocDir struct {
Dan Willemsencc090972018-02-26 14:33:31 -08001216 android.ModuleBase
1217
Nan Zhangf4936b02018-08-01 15:00:28 -07001218 properties ExportedDroiddocDirProperties
Dan Willemsencc090972018-02-26 14:33:31 -08001219
1220 deps android.Paths
1221 dir android.Path
1222}
1223
Nan Zhangf4936b02018-08-01 15:00:28 -07001224func ExportedDroiddocDirFactory() android.Module {
1225 module := &ExportedDroiddocDir{}
Dan Willemsencc090972018-02-26 14:33:31 -08001226 module.AddProperties(&module.properties)
1227 android.InitAndroidModule(module)
1228 return module
1229}
1230
Nan Zhangf4936b02018-08-01 15:00:28 -07001231func (d *ExportedDroiddocDir) DepsMutator(android.BottomUpMutatorContext) {}
Dan Willemsencc090972018-02-26 14:33:31 -08001232
Nan Zhangf4936b02018-08-01 15:00:28 -07001233func (d *ExportedDroiddocDir) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Dan Willemsencc090972018-02-26 14:33:31 -08001234 path := android.PathForModuleSrc(ctx, String(d.properties.Path))
1235 d.dir = path
1236 d.deps = ctx.Glob(path.Join(ctx, "**/*").String(), nil)
1237}
Nan Zhangb2b33de2018-02-23 11:18:47 -08001238
1239//
1240// Defaults
1241//
1242type DocDefaults struct {
1243 android.ModuleBase
1244 android.DefaultsModuleBase
1245}
1246
1247func (*DocDefaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1248}
1249
1250func (d *DocDefaults) DepsMutator(ctx android.BottomUpMutatorContext) {
1251}
1252
1253func DocDefaultsFactory() android.Module {
1254 module := &DocDefaults{}
1255
1256 module.AddProperties(
1257 &JavadocProperties{},
1258 &DroiddocProperties{},
1259 )
1260
1261 android.InitDefaultsModule(module)
1262
1263 return module
1264}