blob: 137eaaffbc4ea799fd37d6270c748673fb60e41e [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{
70 Command: `rm -rf "$outDir" "$srcJarDir" "$stubsDir" && mkdir -p "$outDir" "$srcJarDir" "$stubsDir" && ` +
71 `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
Nan Zhang357466b2018-04-17 17:38:36 -070072 `${config.JavaCmd} -jar ${config.MetalavaJar} -encoding UTF-8 -source $javaVersion @$out.rsp @$srcJarDir/list ` +
Nan Zhang16c0a312018-06-13 17:42:48 -070073 `$bootclasspathArgs $classpathArgs -sourcepath $sourcepath --no-banner --color --quiet ` +
74 `--stubs $stubsDir $opts && ` +
Nan Zhang79614d12018-04-19 18:03:39 -070075 `${config.SoongZipCmd} -write_if_changed -d -o $docZip -C $outDir -D $outDir && ` +
76 `${config.SoongZipCmd} -write_if_changed -jar -o $out -C $stubsDir -D $stubsDir`,
77 CommandDeps: []string{
78 "${config.ZipSyncCmd}",
79 "${config.JavaCmd}",
80 "${config.MetalavaJar}",
81 "${config.JavadocCmd}",
82 "${config.SoongZipCmd}",
83 },
84 Rspfile: "$out.rsp",
85 RspfileContent: "$in",
86 Restat: true,
87 },
Nan Zhang357466b2018-04-17 17:38:36 -070088 "outDir", "srcJarDir", "stubsDir", "srcJars", "javaVersion", "bootclasspathArgs",
89 "classpathArgs", "sourcepath", "opts", "docZip")
Nan Zhang581fd212018-01-10 16:06:12 -080090)
91
92func init() {
Nan Zhangb2b33de2018-02-23 11:18:47 -080093 android.RegisterModuleType("doc_defaults", DocDefaultsFactory)
94
Nan Zhang581fd212018-01-10 16:06:12 -080095 android.RegisterModuleType("droiddoc", DroiddocFactory)
96 android.RegisterModuleType("droiddoc_host", DroiddocHostFactory)
Nan Zhangf4936b02018-08-01 15:00:28 -070097 android.RegisterModuleType("droiddoc_exported_dir", ExportedDroiddocDirFactory)
Nan Zhang581fd212018-01-10 16:06:12 -080098 android.RegisterModuleType("javadoc", JavadocFactory)
99 android.RegisterModuleType("javadoc_host", JavadocHostFactory)
100}
101
Colin Crossa1ce2a02018-06-20 15:19:39 -0700102var (
103 srcsLibTag = dependencyTag{name: "sources from javalib"}
104)
105
Nan Zhang581fd212018-01-10 16:06:12 -0800106type JavadocProperties struct {
107 // list of source files used to compile the Java module. May be .java, .logtags, .proto,
108 // or .aidl files.
109 Srcs []string `android:"arch_variant"`
110
111 // list of directories rooted at the Android.bp file that will
112 // be added to the search paths for finding source files when passing package names.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800113 Local_sourcepaths []string
Nan Zhang581fd212018-01-10 16:06:12 -0800114
115 // list of source files that should not be used to build the Java module.
116 // This is most useful in the arch/multilib variants to remove non-common files
117 // filegroup or genrule can be included within this property.
118 Exclude_srcs []string `android:"arch_variant"`
119
Nan Zhangb2b33de2018-02-23 11:18:47 -0800120 // list of java libraries that will be in the classpath.
Nan Zhang581fd212018-01-10 16:06:12 -0800121 Libs []string `android:"arch_variant"`
122
Nan Zhange66c7272018-03-06 12:59:27 -0800123 // don't build against the framework libraries (legacy-test, core-junit,
124 // ext, and framework for device targets)
125 No_framework_libs *bool
126
Nan Zhangb2b33de2018-02-23 11:18:47 -0800127 // the java library (in classpath) for documentation that provides java srcs and srcjars.
128 Srcs_lib *string
129
130 // the base dirs under srcs_lib will be scanned for java srcs.
131 Srcs_lib_whitelist_dirs []string
132
133 // the sub dirs under srcs_lib_whitelist_dirs will be scanned for java srcs.
134 Srcs_lib_whitelist_pkgs []string
135
Nan Zhang581fd212018-01-10 16:06:12 -0800136 // If set to false, don't allow this module(-docs.zip) to be exported. Defaults to true.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800137 Installable *bool
Nan Zhang581fd212018-01-10 16:06:12 -0800138
139 // if not blank, set to the version of the sdk to compile against
140 Sdk_version *string `android:"arch_variant"`
Jiyong Park1e440682018-05-23 18:42:04 +0900141
142 Aidl struct {
143 // Top level directories to pass to aidl tool
144 Include_dirs []string
145
146 // Directories rooted at the Android.bp file to pass to aidl tool
147 Local_include_dirs []string
148 }
Nan Zhang357466b2018-04-17 17:38:36 -0700149
150 // If not blank, set the java version passed to javadoc as -source
151 Java_version *string
Nan Zhang581fd212018-01-10 16:06:12 -0800152}
153
Nan Zhang61819ce2018-05-04 18:49:16 -0700154type ApiToCheck struct {
Jiyong Parkeeb8a642018-05-12 22:21:20 +0900155 // path to the API txt file that the new API extracted from source code is checked
156 // against. The path can be local to the module or from other module (via :module syntax).
Nan Zhang61819ce2018-05-04 18:49:16 -0700157 Api_file *string
158
Jiyong Parkeeb8a642018-05-12 22:21:20 +0900159 // path to the API txt file that the new @removed API extractd from source code is
160 // checked against. The path can be local to the module or from other module (via
161 // :module syntax).
Nan Zhang61819ce2018-05-04 18:49:16 -0700162 Removed_api_file *string
163
Jiyong Parkeeb8a642018-05-12 22:21:20 +0900164 // Arguments to the apicheck tool.
Nan Zhang61819ce2018-05-04 18:49:16 -0700165 Args *string
166}
167
Nan Zhang581fd212018-01-10 16:06:12 -0800168type DroiddocProperties struct {
169 // directory relative to top of the source tree that contains doc templates files.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800170 Custom_template *string
Nan Zhang581fd212018-01-10 16:06:12 -0800171
Nan Zhanga40da042018-08-01 12:48:00 -0700172 // directories under current module source which contains html/jd files.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800173 Html_dirs []string
Nan Zhang581fd212018-01-10 16:06:12 -0800174
175 // set a value in the Clearsilver hdf namespace.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800176 Hdf []string
Nan Zhang581fd212018-01-10 16:06:12 -0800177
178 // proofread file contains all of the text content of the javadocs concatenated into one file,
179 // suitable for spell-checking and other goodness.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800180 Proofread_file *string
Nan Zhang581fd212018-01-10 16:06:12 -0800181
182 // a todo file lists the program elements that are missing documentation.
183 // At some point, this might be improved to show more warnings.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800184 Todo_file *string
185
186 // directory under current module source that provide additional resources (images).
187 Resourcesdir *string
188
189 // resources output directory under out/soong/.intermediates.
190 Resourcesoutdir *string
Nan Zhang581fd212018-01-10 16:06:12 -0800191
192 // local files that are used within user customized droiddoc options.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800193 Arg_files []string
Nan Zhang581fd212018-01-10 16:06:12 -0800194
195 // user customized droiddoc args.
196 // Available variables for substitution:
197 //
198 // $(location <label>): the path to the arg_files with name <label>
Nan Zhangb2b33de2018-02-23 11:18:47 -0800199 Args *string
Nan Zhang581fd212018-01-10 16:06:12 -0800200
201 // names of the output files used in args that will be generated
Nan Zhangb2b33de2018-02-23 11:18:47 -0800202 Out []string
Nan Zhang581fd212018-01-10 16:06:12 -0800203
Nan Zhange2ba5d42018-07-11 15:16:55 -0700204 // if set to true, collect the values used by the Dev tools and
205 // write them in files packaged with the SDK. Defaults to false.
206 Write_sdk_values *bool
207
208 // index.html under current module will be copied to docs out dir, if not null.
209 Static_doc_index_redirect *string
210
211 // source.properties under current module will be copied to docs out dir, if not null.
212 Static_doc_properties *string
213
Nan Zhang581fd212018-01-10 16:06:12 -0800214 // a list of files under current module source dir which contains known tags in Java sources.
215 // filegroup or genrule can be included within this property.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800216 Knowntags []string
Nan Zhang28c68b92018-03-13 16:17:01 -0700217
218 // the tag name used to distinguish if the API files belong to public/system/test.
219 Api_tag_name *string
220
221 // the generated public API filename by Doclava.
222 Api_filename *string
223
David Brazdilfbe4cc32018-05-31 13:56:46 +0100224 // the generated public Dex API filename by Doclava.
225 Dex_api_filename *string
226
Nan Zhang28c68b92018-03-13 16:17:01 -0700227 // the generated private API filename by Doclava.
228 Private_api_filename *string
229
230 // the generated private Dex API filename by Doclava.
231 Private_dex_api_filename *string
232
233 // the generated removed API filename by Doclava.
234 Removed_api_filename *string
235
David Brazdilaac0c3c2018-04-24 16:23:29 +0100236 // the generated removed Dex API filename by Doclava.
237 Removed_dex_api_filename *string
238
Mathew Inwood76c3de12018-06-22 15:28:11 +0100239 // mapping of dex signatures to source file and line number. This is a temporary property and
240 // will be deleted; you probably shouldn't be using it.
241 Dex_mapping_filename *string
242
Nan Zhang28c68b92018-03-13 16:17:01 -0700243 // the generated exact API filename by Doclava.
244 Exact_api_filename *string
Nan Zhang853f4202018-04-12 16:55:56 -0700245
246 // if set to false, don't allow droiddoc to generate stubs source files. Defaults to true.
247 Create_stubs *bool
Nan Zhang61819ce2018-05-04 18:49:16 -0700248
249 Check_api struct {
250 Last_released ApiToCheck
251
252 Current ApiToCheck
253 }
Nan Zhang79614d12018-04-19 18:03:39 -0700254
255 // if set to true, create stubs through Metalava instead of Doclava. Javadoc/Doclava is
256 // currently still used for documentation generation, and will be replaced by Dokka soon.
257 Metalava_enabled *bool
258
259 // user can specify the version of previous released API file in order to do compatibility check.
260 Metalava_previous_api *string
261
262 // is set to true, Metalava will allow framework SDK to contain annotations.
263 Metalava_annotations_enabled *bool
264
Pete Gillinb13a0152018-07-19 17:56:49 +0100265 // a list of top-level directories containing files to merge annotations from.
266 Metalava_merge_annotations_dirs []string
Nan Zhang581fd212018-01-10 16:06:12 -0800267}
268
Nan Zhanga40da042018-08-01 12:48:00 -0700269//
270// Common flags passed down to build rule
271//
272type droiddocBuilderFlags struct {
273 args string
274 bootClasspathArgs string
275 classpathArgs string
276 aidlFlags string
277
278 doclavaDocsFlags string
279 doclavaStubsFlags string
280 postDoclavaCmds string
281
282 metalavaAnnotationsFlags string
283 metalavaDocsFlags string
284 metalavaStubsFlags string
285
286 dokkaFlags string
287}
288
289func InitDroiddocModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
290 android.InitAndroidArchModule(module, hod, android.MultilibCommon)
291 android.InitDefaultableModule(module)
292}
293
294//
295// Javadoc
296//
Nan Zhang581fd212018-01-10 16:06:12 -0800297type Javadoc struct {
298 android.ModuleBase
299 android.DefaultableModuleBase
300
301 properties JavadocProperties
302
303 srcJars android.Paths
304 srcFiles android.Paths
305 sourcepaths android.Paths
306
Nan Zhangccff0f72018-03-08 17:26:16 -0800307 docZip android.WritablePath
308 stubsSrcJar android.WritablePath
Nan Zhang581fd212018-01-10 16:06:12 -0800309}
310
Nan Zhangb2b33de2018-02-23 11:18:47 -0800311func (j *Javadoc) Srcs() android.Paths {
312 return android.Paths{j.stubsSrcJar}
313}
314
Nan Zhang581fd212018-01-10 16:06:12 -0800315func JavadocFactory() android.Module {
316 module := &Javadoc{}
317
318 module.AddProperties(&module.properties)
319
320 InitDroiddocModule(module, android.HostAndDeviceSupported)
321 return module
322}
323
324func JavadocHostFactory() android.Module {
325 module := &Javadoc{}
326
327 module.AddProperties(&module.properties)
328
329 InitDroiddocModule(module, android.HostSupported)
330 return module
331}
332
Nan Zhanga40da042018-08-01 12:48:00 -0700333var _ android.SourceFileProducer = (*Javadoc)(nil)
Nan Zhang581fd212018-01-10 16:06:12 -0800334
Colin Cross83bb3162018-06-25 15:48:06 -0700335func (j *Javadoc) sdkVersion() string {
336 return String(j.properties.Sdk_version)
337}
338
339func (j *Javadoc) minSdkVersion() string {
340 return j.sdkVersion()
341}
342
Nan Zhang581fd212018-01-10 16:06:12 -0800343func (j *Javadoc) addDeps(ctx android.BottomUpMutatorContext) {
344 if ctx.Device() {
Colin Cross83bb3162018-06-25 15:48:06 -0700345 sdkDep := decodeSdkDep(ctx, sdkContext(j))
Nan Zhang581fd212018-01-10 16:06:12 -0800346 if sdkDep.useDefaultLibs {
347 ctx.AddDependency(ctx.Module(), bootClasspathTag, config.DefaultBootclasspathLibraries...)
Nan Zhang357466b2018-04-17 17:38:36 -0700348 if ctx.Config().TargetOpenJDK9() {
349 ctx.AddDependency(ctx.Module(), systemModulesTag, config.DefaultSystemModules)
350 }
Nan Zhang9cbe6772018-03-21 17:56:39 -0700351 if !Bool(j.properties.No_framework_libs) {
Nan Zhang77a69ec2018-08-02 16:28:26 -0700352 ctx.AddDependency(ctx.Module(), libTag, config.DefaultLibraries...)
Nan Zhange66c7272018-03-06 12:59:27 -0800353 }
Nan Zhang581fd212018-01-10 16:06:12 -0800354 } else if sdkDep.useModule {
Nan Zhang357466b2018-04-17 17:38:36 -0700355 if ctx.Config().TargetOpenJDK9() {
356 ctx.AddDependency(ctx.Module(), systemModulesTag, sdkDep.systemModules)
357 }
Colin Cross86a60ae2018-05-29 14:44:55 -0700358 ctx.AddDependency(ctx.Module(), bootClasspathTag, sdkDep.modules...)
Nan Zhang581fd212018-01-10 16:06:12 -0800359 }
360 }
361
362 ctx.AddDependency(ctx.Module(), libTag, j.properties.Libs...)
Colin Crossa1ce2a02018-06-20 15:19:39 -0700363 if j.properties.Srcs_lib != nil {
364 ctx.AddDependency(ctx.Module(), srcsLibTag, *j.properties.Srcs_lib)
365 }
Nan Zhang581fd212018-01-10 16:06:12 -0800366
367 android.ExtractSourcesDeps(ctx, j.properties.Srcs)
368
369 // exclude_srcs may contain filegroup or genrule.
370 android.ExtractSourcesDeps(ctx, j.properties.Exclude_srcs)
371}
372
Nan Zhangb2b33de2018-02-23 11:18:47 -0800373func (j *Javadoc) genWhitelistPathPrefixes(whitelistPathPrefixes map[string]bool) {
374 for _, dir := range j.properties.Srcs_lib_whitelist_dirs {
375 for _, pkg := range j.properties.Srcs_lib_whitelist_pkgs {
Jiyong Park82484c02018-04-23 21:41:26 +0900376 // convert foo.bar.baz to foo/bar/baz
377 pkgAsPath := filepath.Join(strings.Split(pkg, ".")...)
378 prefix := filepath.Join(dir, pkgAsPath)
Nan Zhangb2b33de2018-02-23 11:18:47 -0800379 if _, found := whitelistPathPrefixes[prefix]; !found {
380 whitelistPathPrefixes[prefix] = true
381 }
382 }
383 }
384}
385
Nan Zhanga40da042018-08-01 12:48:00 -0700386func (j *Javadoc) collectAidlFlags(ctx android.ModuleContext, deps deps) droiddocBuilderFlags {
387 var flags droiddocBuilderFlags
Jiyong Park1e440682018-05-23 18:42:04 +0900388
389 // aidl flags.
390 aidlFlags := j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs)
391 if len(aidlFlags) > 0 {
392 // optimization.
393 ctx.Variable(pctx, "aidlFlags", strings.Join(aidlFlags, " "))
394 flags.aidlFlags = "$aidlFlags"
395 }
396
397 return flags
398}
399
400func (j *Javadoc) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.OptionalPath,
401 aidlIncludeDirs android.Paths) []string {
402
403 aidlIncludes := android.PathsForModuleSrc(ctx, j.properties.Aidl.Local_include_dirs)
404 aidlIncludes = append(aidlIncludes, android.PathsForSource(ctx, j.properties.Aidl.Include_dirs)...)
405
406 var flags []string
407 if aidlPreprocess.Valid() {
408 flags = append(flags, "-p"+aidlPreprocess.String())
409 } else {
410 flags = append(flags, android.JoinWithPrefix(aidlIncludeDirs.Strings(), "-I"))
411 }
412
413 flags = append(flags, android.JoinWithPrefix(aidlIncludes.Strings(), "-I"))
414 flags = append(flags, "-I"+android.PathForModuleSrc(ctx).String())
415 if src := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "src"); src.Valid() {
416 flags = append(flags, "-I"+src.String())
417 }
418
419 return flags
420}
421
422func (j *Javadoc) genSources(ctx android.ModuleContext, srcFiles android.Paths,
Nan Zhanga40da042018-08-01 12:48:00 -0700423 flags droiddocBuilderFlags) android.Paths {
Jiyong Park1e440682018-05-23 18:42:04 +0900424
425 outSrcFiles := make(android.Paths, 0, len(srcFiles))
426
427 for _, srcFile := range srcFiles {
428 switch srcFile.Ext() {
429 case ".aidl":
430 javaFile := genAidl(ctx, srcFile, flags.aidlFlags)
431 outSrcFiles = append(outSrcFiles, javaFile)
432 default:
433 outSrcFiles = append(outSrcFiles, srcFile)
434 }
435 }
436
437 return outSrcFiles
438}
439
Nan Zhang581fd212018-01-10 16:06:12 -0800440func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps {
441 var deps deps
442
Colin Cross83bb3162018-06-25 15:48:06 -0700443 sdkDep := decodeSdkDep(ctx, sdkContext(j))
Nan Zhang581fd212018-01-10 16:06:12 -0800444 if sdkDep.invalidVersion {
Colin Cross86a60ae2018-05-29 14:44:55 -0700445 ctx.AddMissingDependencies(sdkDep.modules)
Nan Zhang581fd212018-01-10 16:06:12 -0800446 } else if sdkDep.useFiles {
Colin Cross86a60ae2018-05-29 14:44:55 -0700447 deps.bootClasspath = append(deps.bootClasspath, sdkDep.jars...)
Nan Zhang581fd212018-01-10 16:06:12 -0800448 }
449
450 ctx.VisitDirectDeps(func(module android.Module) {
451 otherName := ctx.OtherModuleName(module)
452 tag := ctx.OtherModuleDependencyTag(module)
453
Colin Cross2d24c1b2018-05-23 10:59:18 -0700454 switch tag {
455 case bootClasspathTag:
456 if dep, ok := module.(Dependency); ok {
Nan Zhang581fd212018-01-10 16:06:12 -0800457 deps.bootClasspath = append(deps.bootClasspath, dep.ImplementationJars()...)
Colin Cross2d24c1b2018-05-23 10:59:18 -0700458 } else {
459 panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
460 }
461 case libTag:
462 switch dep := module.(type) {
463 case Dependency:
Nan Zhang581fd212018-01-10 16:06:12 -0800464 deps.classpath = append(deps.classpath, dep.ImplementationJars()...)
Colin Cross2d24c1b2018-05-23 10:59:18 -0700465 case SdkLibraryDependency:
Colin Cross83bb3162018-06-25 15:48:06 -0700466 sdkVersion := j.sdkVersion()
Jiyong Parkc678ad32018-04-10 13:07:10 +0900467 linkType := javaSdk
468 if strings.HasPrefix(sdkVersion, "system_") || strings.HasPrefix(sdkVersion, "test_") {
469 linkType = javaSystem
470 } else if sdkVersion == "" {
471 linkType = javaPlatform
472 }
Sundong Ahn241cd372018-07-13 16:16:44 +0900473 deps.classpath = append(deps.classpath, dep.ImplementationJars(linkType)...)
Colin Cross2d24c1b2018-05-23 10:59:18 -0700474 case android.SourceFileProducer:
Nan Zhang581fd212018-01-10 16:06:12 -0800475 checkProducesJars(ctx, dep)
476 deps.classpath = append(deps.classpath, dep.Srcs()...)
Nan Zhang581fd212018-01-10 16:06:12 -0800477 default:
478 ctx.ModuleErrorf("depends on non-java module %q", otherName)
479 }
Colin Crossa1ce2a02018-06-20 15:19:39 -0700480 case srcsLibTag:
481 switch dep := module.(type) {
482 case Dependency:
483 srcs := dep.(SrcDependency).CompiledSrcs()
484 whitelistPathPrefixes := make(map[string]bool)
485 j.genWhitelistPathPrefixes(whitelistPathPrefixes)
486 for _, src := range srcs {
487 if _, ok := src.(android.WritablePath); ok { // generated sources
488 deps.srcs = append(deps.srcs, src)
489 } else { // select source path for documentation based on whitelist path prefixs.
490 for k, _ := range whitelistPathPrefixes {
491 if strings.HasPrefix(src.Rel(), k) {
492 deps.srcs = append(deps.srcs, src)
493 break
494 }
495 }
496 }
497 }
498 deps.srcJars = append(deps.srcJars, dep.(SrcDependency).CompiledSrcJars()...)
499 default:
500 ctx.ModuleErrorf("depends on non-java module %q", otherName)
501 }
Nan Zhang357466b2018-04-17 17:38:36 -0700502 case systemModulesTag:
503 if deps.systemModules != nil {
504 panic("Found two system module dependencies")
505 }
506 sm := module.(*SystemModules)
507 if sm.outputFile == nil {
508 panic("Missing directory for system module dependency")
509 }
510 deps.systemModules = sm.outputFile
Nan Zhang581fd212018-01-10 16:06:12 -0800511 }
512 })
513 // do not pass exclude_srcs directly when expanding srcFiles since exclude_srcs
514 // may contain filegroup or genrule.
515 srcFiles := ctx.ExpandSources(j.properties.Srcs, j.properties.Exclude_srcs)
Nan Zhanga40da042018-08-01 12:48:00 -0700516 flags := j.collectAidlFlags(ctx, deps)
Jiyong Park1e440682018-05-23 18:42:04 +0900517 srcFiles = j.genSources(ctx, srcFiles, flags)
Nan Zhang581fd212018-01-10 16:06:12 -0800518
519 // srcs may depend on some genrule output.
520 j.srcJars = srcFiles.FilterByExt(".srcjar")
Nan Zhangb2b33de2018-02-23 11:18:47 -0800521 j.srcJars = append(j.srcJars, deps.srcJars...)
522
Nan Zhang581fd212018-01-10 16:06:12 -0800523 j.srcFiles = srcFiles.FilterOutByExt(".srcjar")
Nan Zhangb2b33de2018-02-23 11:18:47 -0800524 j.srcFiles = append(j.srcFiles, deps.srcs...)
Nan Zhang581fd212018-01-10 16:06:12 -0800525
526 j.docZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"docs.zip")
Nan Zhangccff0f72018-03-08 17:26:16 -0800527 j.stubsSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
Nan Zhang581fd212018-01-10 16:06:12 -0800528
529 if j.properties.Local_sourcepaths == nil {
530 j.properties.Local_sourcepaths = append(j.properties.Local_sourcepaths, ".")
531 }
532 j.sourcepaths = android.PathsForModuleSrc(ctx, j.properties.Local_sourcepaths)
Nan Zhang581fd212018-01-10 16:06:12 -0800533
534 return deps
535}
536
537func (j *Javadoc) DepsMutator(ctx android.BottomUpMutatorContext) {
538 j.addDeps(ctx)
539}
540
541func (j *Javadoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
542 deps := j.collectDeps(ctx)
543
544 var implicits android.Paths
545 implicits = append(implicits, deps.bootClasspath...)
546 implicits = append(implicits, deps.classpath...)
547
548 var bootClasspathArgs, classpathArgs string
Nan Zhang357466b2018-04-17 17:38:36 -0700549
Colin Cross83bb3162018-06-25 15:48:06 -0700550 javaVersion := getJavaVersion(ctx, String(j.properties.Java_version), sdkContext(j))
Colin Cross997262f2018-06-19 22:49:39 -0700551 if len(deps.bootClasspath) > 0 {
552 var systemModules classpath
553 if deps.systemModules != nil {
554 systemModules = append(systemModules, deps.systemModules)
Nan Zhang581fd212018-01-10 16:06:12 -0800555 }
Colin Cross997262f2018-06-19 22:49:39 -0700556 bootClasspathArgs = systemModules.FormJavaSystemModulesPath("--system ", ctx.Device())
557 bootClasspathArgs = bootClasspathArgs + " --patch-module java.base=."
Nan Zhang581fd212018-01-10 16:06:12 -0800558 }
559 if len(deps.classpath.Strings()) > 0 {
560 classpathArgs = "-classpath " + strings.Join(deps.classpath.Strings(), ":")
561 }
562
563 implicits = append(implicits, j.srcJars...)
564
Nan Zhangaf322cc2018-06-19 15:15:38 -0700565 opts := "-source " + javaVersion + " -J-Xmx1024m -XDignore.symbol.file -Xdoclint:none"
Nan Zhang581fd212018-01-10 16:06:12 -0800566
567 ctx.Build(pctx, android.BuildParams{
568 Rule: javadoc,
569 Description: "Javadoc",
Nan Zhangccff0f72018-03-08 17:26:16 -0800570 Output: j.stubsSrcJar,
Nan Zhang581fd212018-01-10 16:06:12 -0800571 ImplicitOutput: j.docZip,
572 Inputs: j.srcFiles,
573 Implicits: implicits,
574 Args: map[string]string{
575 "outDir": android.PathForModuleOut(ctx, "docs", "out").String(),
576 "srcJarDir": android.PathForModuleOut(ctx, "docs", "srcjars").String(),
577 "stubsDir": android.PathForModuleOut(ctx, "docs", "stubsDir").String(),
578 "srcJars": strings.Join(j.srcJars.Strings(), " "),
579 "opts": opts,
Nan Zhang853f4202018-04-12 16:55:56 -0700580 "bootclasspathArgs": bootClasspathArgs,
Nan Zhang581fd212018-01-10 16:06:12 -0800581 "classpathArgs": classpathArgs,
582 "sourcepath": strings.Join(j.sourcepaths.Strings(), ":"),
583 "docZip": j.docZip.String(),
584 },
585 })
586}
587
Nan Zhanga40da042018-08-01 12:48:00 -0700588//
589// Droiddoc
590//
591type Droiddoc struct {
592 Javadoc
593
594 properties DroiddocProperties
595 apiFile android.WritablePath
596 dexApiFile android.WritablePath
597 privateApiFile android.WritablePath
598 privateDexApiFile android.WritablePath
599 removedApiFile android.WritablePath
600 removedDexApiFile android.WritablePath
601 exactApiFile android.WritablePath
602 apiMappingFile android.WritablePath
603
604 checkCurrentApiTimestamp android.WritablePath
605 updateCurrentApiTimestamp android.WritablePath
606 checkLastReleasedApiTimestamp android.WritablePath
607
608 annotationsZip android.WritablePath
609
610 apiFilePath android.Path
611}
612
613type ApiFilePath interface {
614 ApiFilePath() android.Path
615}
616
617func DroiddocFactory() android.Module {
618 module := &Droiddoc{}
619
620 module.AddProperties(&module.properties,
621 &module.Javadoc.properties)
622
623 InitDroiddocModule(module, android.HostAndDeviceSupported)
624 return module
625}
626
627func DroiddocHostFactory() android.Module {
628 module := &Droiddoc{}
629
630 module.AddProperties(&module.properties,
631 &module.Javadoc.properties)
632
633 InitDroiddocModule(module, android.HostSupported)
634 return module
635}
636
637func (d *Droiddoc) ApiFilePath() android.Path {
638 return d.apiFilePath
639}
640
Nan Zhang61819ce2018-05-04 18:49:16 -0700641func (d *Droiddoc) checkCurrentApi() bool {
642 if String(d.properties.Check_api.Current.Api_file) != "" &&
643 String(d.properties.Check_api.Current.Removed_api_file) != "" {
644 return true
645 } else if String(d.properties.Check_api.Current.Api_file) != "" {
646 panic("check_api.current.removed_api_file: has to be non empty!")
647 } else if String(d.properties.Check_api.Current.Removed_api_file) != "" {
648 panic("check_api.current.api_file: has to be non empty!")
649 }
650
651 return false
652}
653
654func (d *Droiddoc) checkLastReleasedApi() bool {
655 if String(d.properties.Check_api.Last_released.Api_file) != "" &&
656 String(d.properties.Check_api.Last_released.Removed_api_file) != "" {
657 return true
658 } else if String(d.properties.Check_api.Last_released.Api_file) != "" {
659 panic("check_api.last_released.removed_api_file: has to be non empty!")
660 } else if String(d.properties.Check_api.Last_released.Removed_api_file) != "" {
661 panic("check_api.last_released.api_file: has to be non empty!")
662 }
663
664 return false
665}
666
Nan Zhang581fd212018-01-10 16:06:12 -0800667func (d *Droiddoc) DepsMutator(ctx android.BottomUpMutatorContext) {
668 d.Javadoc.addDeps(ctx)
669
Nan Zhang79614d12018-04-19 18:03:39 -0700670 if String(d.properties.Custom_template) != "" {
Dan Willemsencc090972018-02-26 14:33:31 -0800671 ctx.AddDependency(ctx.Module(), droiddocTemplateTag, String(d.properties.Custom_template))
672 }
673
Nan Zhanga40da042018-08-01 12:48:00 -0700674 // arg_files may contains filegroup or genrule.
Nan Zhang581fd212018-01-10 16:06:12 -0800675 android.ExtractSourcesDeps(ctx, d.properties.Arg_files)
676
677 // knowntags may contain filegroup or genrule.
678 android.ExtractSourcesDeps(ctx, d.properties.Knowntags)
Nan Zhang61819ce2018-05-04 18:49:16 -0700679
Nan Zhange2ba5d42018-07-11 15:16:55 -0700680 if String(d.properties.Static_doc_index_redirect) != "" {
681 android.ExtractSourceDeps(ctx, d.properties.Static_doc_index_redirect)
682 }
683
684 if String(d.properties.Static_doc_properties) != "" {
685 android.ExtractSourceDeps(ctx, d.properties.Static_doc_properties)
686 }
687
Nan Zhang61819ce2018-05-04 18:49:16 -0700688 if d.checkCurrentApi() {
689 android.ExtractSourceDeps(ctx, d.properties.Check_api.Current.Api_file)
690 android.ExtractSourceDeps(ctx, d.properties.Check_api.Current.Removed_api_file)
691 }
692
693 if d.checkLastReleasedApi() {
694 android.ExtractSourceDeps(ctx, d.properties.Check_api.Last_released.Api_file)
695 android.ExtractSourceDeps(ctx, d.properties.Check_api.Last_released.Removed_api_file)
696 }
Nan Zhang79614d12018-04-19 18:03:39 -0700697
698 if String(d.properties.Metalava_previous_api) != "" {
699 android.ExtractSourceDeps(ctx, d.properties.Metalava_previous_api)
700 }
Nan Zhangf4936b02018-08-01 15:00:28 -0700701
702 if len(d.properties.Metalava_merge_annotations_dirs) != 0 {
703 for _, mergeAnnotationsDir := range d.properties.Metalava_merge_annotations_dirs {
704 ctx.AddDependency(ctx.Module(), metalavaMergeAnnotationsDirTag, mergeAnnotationsDir)
705 }
706 }
Nan Zhang581fd212018-01-10 16:06:12 -0800707}
708
Nan Zhanga40da042018-08-01 12:48:00 -0700709func (d *Droiddoc) initBuilderFlags(ctx android.ModuleContext, implicits *android.Paths, deps deps) (droiddocBuilderFlags, error) {
710 var flags droiddocBuilderFlags
Nan Zhang581fd212018-01-10 16:06:12 -0800711
Nan Zhanga40da042018-08-01 12:48:00 -0700712 *implicits = append(*implicits, deps.bootClasspath...)
713 *implicits = append(*implicits, deps.classpath...)
Nan Zhang581fd212018-01-10 16:06:12 -0800714
Nan Zhangc94f9d82018-06-26 10:02:26 -0700715 // continue to use -bootclasspath even if Metalava under -source 1.9 is enabled
716 // since it doesn't support system modules yet.
717 if len(deps.bootClasspath.Strings()) > 0 {
718 // For OpenJDK 8 we can use -bootclasspath to define the core libraries code.
Nan Zhanga40da042018-08-01 12:48:00 -0700719 flags.bootClasspathArgs = deps.bootClasspath.FormJavaClassPath("-bootclasspath")
Nan Zhang357466b2018-04-17 17:38:36 -0700720 }
Nan Zhanga40da042018-08-01 12:48:00 -0700721 flags.classpathArgs = deps.classpath.FormJavaClassPath("-classpath")
Nan Zhang79614d12018-04-19 18:03:39 -0700722
Nan Zhang581fd212018-01-10 16:06:12 -0800723 argFiles := ctx.ExpandSources(d.properties.Arg_files, nil)
724 argFilesMap := map[string]android.Path{}
725
726 for _, f := range argFiles {
Nan Zhanga40da042018-08-01 12:48:00 -0700727 *implicits = append(*implicits, f)
Nan Zhang581fd212018-01-10 16:06:12 -0800728 if _, exists := argFilesMap[f.Rel()]; !exists {
729 argFilesMap[f.Rel()] = f
730 } else {
731 ctx.ModuleErrorf("multiple arg_files for %q, %q and %q",
732 f, argFilesMap[f.Rel()], f.Rel())
733 }
734 }
735
Nan Zhanga40da042018-08-01 12:48:00 -0700736 var err error
737 flags.args, err = android.Expand(String(d.properties.Args), func(name string) (string, error) {
Nan Zhang581fd212018-01-10 16:06:12 -0800738 if strings.HasPrefix(name, "location ") {
739 label := strings.TrimSpace(strings.TrimPrefix(name, "location "))
740 if f, ok := argFilesMap[label]; ok {
741 return f.String(), nil
742 } else {
743 return "", fmt.Errorf("unknown location label %q", label)
744 }
745 } else if name == "genDir" {
746 return android.PathForModuleGen(ctx).String(), nil
747 }
748 return "", fmt.Errorf("unknown variable '$(%s)'", name)
749 })
750
751 if err != nil {
Nan Zhang79614d12018-04-19 18:03:39 -0700752 ctx.PropertyErrorf("args", "%s", err.Error())
Nan Zhanga40da042018-08-01 12:48:00 -0700753 return droiddocBuilderFlags{}, err
Nan Zhang581fd212018-01-10 16:06:12 -0800754 }
Nan Zhanga40da042018-08-01 12:48:00 -0700755 return flags, nil
756}
Nan Zhang581fd212018-01-10 16:06:12 -0800757
Nan Zhanga40da042018-08-01 12:48:00 -0700758func (d *Droiddoc) collectDoclavaDocsFlags(ctx android.ModuleContext, implicits *android.Paths,
759 javaVersion string, jsilver, doclava android.Path) string {
Nan Zhang581fd212018-01-10 16:06:12 -0800760
Nan Zhanga40da042018-08-01 12:48:00 -0700761 *implicits = append(*implicits, jsilver)
762 *implicits = append(*implicits, doclava)
Nan Zhang30963742018-04-23 09:59:14 -0700763
Nan Zhang46130972018-06-04 11:28:01 -0700764 var date string
765 if runtime.GOOS == "darwin" {
766 date = `date -r`
767 } else {
768 date = `date -d`
769 }
770
Nan Zhanga40da042018-08-01 12:48:00 -0700771 args := " -source " + javaVersion + " -J-Xmx1600m -J-XX:-OmitStackTraceInFastThrow -XDignore.symbol.file " +
Nan Zhang30963742018-04-23 09:59:14 -0700772 "-doclet com.google.doclava.Doclava -docletpath " + jsilver.String() + ":" + doclava.String() + " " +
Nan Zhang581fd212018-01-10 16:06:12 -0800773 "-hdf page.build " + ctx.Config().BuildId() + "-" + ctx.Config().BuildNumberFromFile() + " " +
Nan Zhang79614d12018-04-19 18:03:39 -0700774 `-hdf page.now "$$(` + date + ` @$$(cat ` + ctx.Config().Getenv("BUILD_DATETIME_FILE") + `) "+%d %b %Y %k:%M")" `
Nan Zhang46130972018-06-04 11:28:01 -0700775
Nan Zhanga40da042018-08-01 12:48:00 -0700776 if String(d.properties.Custom_template) == "" {
777 // TODO: This is almost always droiddoc-templates-sdk
778 ctx.PropertyErrorf("custom_template", "must specify a template")
779 }
780
781 ctx.VisitDirectDepsWithTag(droiddocTemplateTag, func(m android.Module) {
Nan Zhangf4936b02018-08-01 15:00:28 -0700782 if t, ok := m.(*ExportedDroiddocDir); ok {
Nan Zhanga40da042018-08-01 12:48:00 -0700783 *implicits = append(*implicits, t.deps...)
784 args = args + " -templatedir " + t.dir.String()
785 } else {
786 ctx.PropertyErrorf("custom_template", "module %q is not a droiddoc_template", ctx.OtherModuleName(m))
787 }
788 })
789
790 if len(d.properties.Html_dirs) > 0 {
791 htmlDir := android.PathForModuleSrc(ctx, d.properties.Html_dirs[0])
792 *implicits = append(*implicits, ctx.Glob(htmlDir.Join(ctx, "**/*").String(), nil)...)
793 args = args + " -htmldir " + htmlDir.String()
794 }
795
796 if len(d.properties.Html_dirs) > 1 {
797 htmlDir2 := android.PathForModuleSrc(ctx, d.properties.Html_dirs[1])
798 *implicits = append(*implicits, ctx.Glob(htmlDir2.Join(ctx, "**/*").String(), nil)...)
799 args = args + " -htmldir2 " + htmlDir2.String()
800 }
801
802 if len(d.properties.Html_dirs) > 2 {
803 ctx.PropertyErrorf("html_dirs", "Droiddoc only supports up to 2 html dirs")
804 }
805
806 knownTags := ctx.ExpandSources(d.properties.Knowntags, nil)
807 *implicits = append(*implicits, knownTags...)
808
809 for _, kt := range knownTags {
810 args = args + " -knowntags " + kt.String()
811 }
812
813 for _, hdf := range d.properties.Hdf {
814 args = args + " -hdf " + hdf
815 }
816
817 if String(d.properties.Proofread_file) != "" {
818 proofreadFile := android.PathForModuleOut(ctx, String(d.properties.Proofread_file))
819 args = args + " -proofread " + proofreadFile.String()
820 }
821
822 if String(d.properties.Todo_file) != "" {
823 // tricky part:
824 // we should not compute full path for todo_file through PathForModuleOut().
825 // the non-standard doclet will get the full path relative to "-o".
826 args = args + " -todo " + String(d.properties.Todo_file)
827 }
828
829 if String(d.properties.Resourcesdir) != "" {
830 // TODO: should we add files under resourcesDir to the implicits? It seems that
831 // resourcesDir is one sub dir of htmlDir
832 resourcesDir := android.PathForModuleSrc(ctx, String(d.properties.Resourcesdir))
833 args = args + " -resourcesdir " + resourcesDir.String()
834 }
835
836 if String(d.properties.Resourcesoutdir) != "" {
837 // TODO: it seems -resourceoutdir reference/android/images/ didn't get generated anywhere.
838 args = args + " -resourcesoutdir " + String(d.properties.Resourcesoutdir)
839 }
840 return args
841}
842
843func (d *Droiddoc) collectStubsFlags(ctx android.ModuleContext, implicitOutputs *android.WritablePaths) (string, string) {
844 var doclavaFlags, MetalavaFlags string
845 if d.checkCurrentApi() || d.checkLastReleasedApi() || String(d.properties.Api_filename) != "" {
846 d.apiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_api.txt")
847 doclavaFlags += " -api " + d.apiFile.String()
848 MetalavaFlags = MetalavaFlags + " --api " + d.apiFile.String()
849 *implicitOutputs = append(*implicitOutputs, d.apiFile)
850 d.apiFilePath = d.apiFile
851 }
852
853 if d.checkCurrentApi() || d.checkLastReleasedApi() || String(d.properties.Removed_api_filename) != "" {
854 d.removedApiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_removed.txt")
855 doclavaFlags += " -removedApi " + d.removedApiFile.String()
856 MetalavaFlags = MetalavaFlags + " --removed-api " + d.removedApiFile.String()
857 *implicitOutputs = append(*implicitOutputs, d.removedApiFile)
858 }
859
860 if String(d.properties.Private_api_filename) != "" {
861 d.privateApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_api_filename))
862 doclavaFlags += " -privateApi " + d.privateApiFile.String()
863 MetalavaFlags = MetalavaFlags + " --private-api " + d.privateApiFile.String()
864 *implicitOutputs = append(*implicitOutputs, d.privateApiFile)
865 }
866
867 if String(d.properties.Dex_api_filename) != "" {
868 d.dexApiFile = android.PathForModuleOut(ctx, String(d.properties.Dex_api_filename))
869 doclavaFlags += " -dexApi " + d.dexApiFile.String()
870 *implicitOutputs = append(*implicitOutputs, d.dexApiFile)
871 }
872
873 if String(d.properties.Private_dex_api_filename) != "" {
874 d.privateDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_dex_api_filename))
875 doclavaFlags += " -privateDexApi " + d.privateDexApiFile.String()
876 MetalavaFlags = MetalavaFlags + " --private-dex-api " + d.privateDexApiFile.String()
877 *implicitOutputs = append(*implicitOutputs, d.privateDexApiFile)
878 }
879
880 if String(d.properties.Removed_dex_api_filename) != "" {
881 d.removedDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Removed_dex_api_filename))
882 doclavaFlags += " -removedDexApi " + d.removedDexApiFile.String()
883 MetalavaFlags = MetalavaFlags + " --removed-dex-api " + d.removedDexApiFile.String()
884 *implicitOutputs = append(*implicitOutputs, d.removedDexApiFile)
885 }
886
887 if String(d.properties.Exact_api_filename) != "" {
888 d.exactApiFile = android.PathForModuleOut(ctx, String(d.properties.Exact_api_filename))
889 doclavaFlags += " -exactApi " + d.exactApiFile.String()
890 MetalavaFlags = MetalavaFlags + " --exact-api " + d.exactApiFile.String()
891 *implicitOutputs = append(*implicitOutputs, d.exactApiFile)
892 }
893
894 if String(d.properties.Dex_mapping_filename) != "" {
895 d.apiMappingFile = android.PathForModuleOut(ctx, String(d.properties.Dex_mapping_filename))
896 doclavaFlags += " -apiMapping " + d.apiMappingFile.String()
897 // Omitted: metalava support
898 *implicitOutputs = append(*implicitOutputs, d.apiMappingFile)
899 }
900
901 if BoolDefault(d.properties.Create_stubs, true) {
902 doclavaFlags += " -stubs " + android.PathForModuleOut(ctx, "docs", "stubsDir").String()
903 }
904
905 if Bool(d.properties.Write_sdk_values) {
906 doclavaFlags += " -sdkvalues " + android.PathForModuleOut(ctx, "docs", "out").String()
907 }
908 return doclavaFlags, MetalavaFlags
909}
910
911func (d *Droiddoc) getPostDoclavaCmds(ctx android.ModuleContext, implicits *android.Paths) string {
912 var cmds string
913 if String(d.properties.Static_doc_index_redirect) != "" {
914 static_doc_index_redirect := ctx.ExpandSource(String(d.properties.Static_doc_index_redirect),
915 "static_doc_index_redirect")
916 *implicits = append(*implicits, static_doc_index_redirect)
917 cmds = cmds + " && cp " + static_doc_index_redirect.String() + " " +
918 android.PathForModuleOut(ctx, "docs", "out", "index.html").String()
919 }
920
921 if String(d.properties.Static_doc_properties) != "" {
922 static_doc_properties := ctx.ExpandSource(String(d.properties.Static_doc_properties),
923 "static_doc_properties")
924 *implicits = append(*implicits, static_doc_properties)
925 cmds = cmds + " && cp " + static_doc_properties.String() + " " +
926 android.PathForModuleOut(ctx, "docs", "out", "source.properties").String()
927 }
928 return cmds
929}
930
931func (d *Droiddoc) collectMetalavaAnnotationsFlags(
932 ctx android.ModuleContext, implicits *android.Paths, implicitOutputs *android.WritablePaths) string {
933 var flags string
934 if String(d.properties.Metalava_previous_api) != "" {
935 previousApi := ctx.ExpandSource(String(d.properties.Metalava_previous_api),
936 "metalava_previous_api")
937 flags += " --previous-api " + previousApi.String()
938 *implicits = append(*implicits, previousApi)
939 }
940
941 if Bool(d.properties.Metalava_annotations_enabled) {
942 if String(d.properties.Metalava_previous_api) == "" {
943 ctx.PropertyErrorf("metalava_previous_api",
944 "has to be non-empty if annotations was enabled!")
945 }
946 flags += " --include-annotations --migrate-nullness"
947
948 d.annotationsZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"_annotations.zip")
949 *implicitOutputs = append(*implicitOutputs, d.annotationsZip)
950
Nan Zhangf4936b02018-08-01 15:00:28 -0700951 flags += " --extract-annotations " + d.annotationsZip.String()
952
Nan Zhanga40da042018-08-01 12:48:00 -0700953 if len(d.properties.Metalava_merge_annotations_dirs) == 0 {
954 ctx.PropertyErrorf("metalava_merge_annotations_dirs",
955 "has to be non-empty if annotations was enabled!")
956 }
Nan Zhangf4936b02018-08-01 15:00:28 -0700957 ctx.VisitDirectDepsWithTag(metalavaMergeAnnotationsDirTag, func(m android.Module) {
958 if t, ok := m.(*ExportedDroiddocDir); ok {
959 *implicits = append(*implicits, t.deps...)
960 flags += " --merge-annotations " + t.dir.String()
961 } else {
962 ctx.PropertyErrorf("metalava_merge_annotations_dirs",
963 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
964 }
965 })
Nan Zhanga40da042018-08-01 12:48:00 -0700966 // TODO(tnorbye): find owners to fix these warnings when annotation was enabled.
967 flags += " --hide HiddenTypedefConstant --hide SuperfluousPrefix --hide AnnotationExtraction "
968 }
969
970 return flags
971}
972
973func (d *Droiddoc) collectMetalavaDocsFlags(ctx android.ModuleContext,
974 bootClasspathArgs, classpathArgs string) string {
975 return " --doc-stubs " + android.PathForModuleOut(ctx, "docs", "docStubsDir").String() +
976 " --write-doc-stubs-source-list $outDir/doc_stubs_src_list " +
977 " --generate-documentation ${config.JavadocCmd} -encoding UTF-8 DOC_STUBS_SOURCE_LIST " +
978 bootClasspathArgs + " " + classpathArgs + " " + " -sourcepath " +
979 android.PathForModuleOut(ctx, "docs", "docStubsDir").String() + " -quiet -d $outDir "
980}
981
982func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
983 deps := d.Javadoc.collectDeps(ctx)
984
985 javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), sdkContext(d))
986 // Doclava has problem with "-source 1.9", so override javaVersion when Doclava
987 // is running with EXPERIMENTAL_USE_OPENJDK9=true. And eventually Doclava will be
988 // replaced by Metalava.
Nan Zhang79614d12018-04-19 18:03:39 -0700989 if !Bool(d.properties.Metalava_enabled) {
Nan Zhanga40da042018-08-01 12:48:00 -0700990 javaVersion = "1.8"
991 }
Nan Zhang581fd212018-01-10 16:06:12 -0800992
Nan Zhanga40da042018-08-01 12:48:00 -0700993 jsilver := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "jsilver.jar")
994 doclava := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "doclava.jar")
995 java8Home := ctx.Config().Getenv("ANDROID_JAVA8_HOME")
996 checkApiClasspath := classpath{jsilver, doclava, android.PathForSource(ctx, java8Home, "lib/tools.jar")}
Nan Zhang581fd212018-01-10 16:06:12 -0800997
Nan Zhanga40da042018-08-01 12:48:00 -0700998 var implicits android.Paths
999 implicits = append(implicits, d.Javadoc.srcJars...)
1000
1001 var implicitOutputs android.WritablePaths
1002 implicitOutputs = append(implicitOutputs, d.Javadoc.docZip)
1003 for _, o := range d.properties.Out {
1004 implicitOutputs = append(implicitOutputs, android.PathForModuleGen(ctx, o))
1005 }
1006
1007 flags, err := d.initBuilderFlags(ctx, &implicits, deps)
1008 if err != nil {
1009 return
1010 }
1011
1012 flags.doclavaStubsFlags, flags.metalavaStubsFlags = d.collectStubsFlags(ctx, &implicitOutputs)
1013 if Bool(d.properties.Metalava_enabled) {
1014 opts := flags.metalavaStubsFlags
1015 flags.metalavaAnnotationsFlags = d.collectMetalavaAnnotationsFlags(ctx, &implicits, &implicitOutputs)
1016 opts += flags.metalavaAnnotationsFlags
1017 if strings.Contains(flags.args, "--generate-documentation") {
1018 // TODO(nanzhang): Add a Soong property to handle documentation args.
1019 flags.doclavaDocsFlags = d.collectDoclavaDocsFlags(ctx, &implicits, javaVersion, jsilver, doclava)
1020 flags.metalavaDocsFlags = d.collectMetalavaDocsFlags(ctx, flags.bootClasspathArgs, flags.classpathArgs)
1021 opts += " " + strings.Split(flags.args, "--generate-documentation")[0] + " " +
1022 flags.metalavaDocsFlags + flags.doclavaDocsFlags +
1023 " " + strings.Split(flags.args, "--generate-documentation")[1]
1024 } else {
1025 opts += " " + flags.args
Nan Zhang79614d12018-04-19 18:03:39 -07001026 }
Nan Zhanga40da042018-08-01 12:48:00 -07001027 ctx.Build(pctx, android.BuildParams{
1028 Rule: metalava,
1029 Description: "Metalava",
1030 Output: d.Javadoc.stubsSrcJar,
1031 Inputs: d.Javadoc.srcFiles,
1032 Implicits: implicits,
1033 ImplicitOutputs: implicitOutputs,
1034 Args: map[string]string{
1035 "outDir": android.PathForModuleOut(ctx, "docs", "out").String(),
1036 "srcJarDir": android.PathForModuleOut(ctx, "docs", "srcjars").String(),
1037 "stubsDir": android.PathForModuleOut(ctx, "docs", "stubsDir").String(),
1038 "srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "),
1039 "javaVersion": javaVersion,
1040 "bootclasspathArgs": flags.bootClasspathArgs,
1041 "classpathArgs": flags.classpathArgs,
1042 "sourcepath": strings.Join(d.Javadoc.sourcepaths.Strings(), ":"),
1043 "docZip": d.Javadoc.docZip.String(),
1044 "opts": opts,
1045 },
1046 })
1047 } else {
1048 flags.doclavaDocsFlags = d.collectDoclavaDocsFlags(ctx, &implicits, javaVersion, jsilver, doclava)
1049 flags.postDoclavaCmds = d.getPostDoclavaCmds(ctx, &implicits)
Nan Zhang79614d12018-04-19 18:03:39 -07001050 ctx.Build(pctx, android.BuildParams{
1051 Rule: javadoc,
1052 Description: "Droiddoc",
1053 Output: d.Javadoc.stubsSrcJar,
1054 Inputs: d.Javadoc.srcFiles,
1055 Implicits: implicits,
1056 ImplicitOutputs: implicitOutputs,
1057 Args: map[string]string{
1058 "outDir": android.PathForModuleOut(ctx, "docs", "out").String(),
1059 "srcJarDir": android.PathForModuleOut(ctx, "docs", "srcjars").String(),
1060 "stubsDir": android.PathForModuleOut(ctx, "docs", "stubsDir").String(),
1061 "srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "),
Nan Zhanga40da042018-08-01 12:48:00 -07001062 "opts": flags.doclavaDocsFlags + flags.doclavaStubsFlags + " " + flags.args,
1063 "bootclasspathArgs": flags.bootClasspathArgs,
1064 "classpathArgs": flags.classpathArgs,
Nan Zhang79614d12018-04-19 18:03:39 -07001065 "sourcepath": strings.Join(d.Javadoc.sourcepaths.Strings(), ":"),
1066 "docZip": d.Javadoc.docZip.String(),
Nan Zhanga40da042018-08-01 12:48:00 -07001067 "postDoclavaCmds": flags.postDoclavaCmds,
Nan Zhang79614d12018-04-19 18:03:39 -07001068 },
1069 })
Nan Zhang79614d12018-04-19 18:03:39 -07001070 }
Nan Zhang61819ce2018-05-04 18:49:16 -07001071
Nan Zhang61819ce2018-05-04 18:49:16 -07001072 if d.checkCurrentApi() && !ctx.Config().IsPdkBuild() {
1073 d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, "check_current_api.timestamp")
1074
1075 apiFile := ctx.ExpandSource(String(d.properties.Check_api.Current.Api_file),
1076 "check_api.current.api_file")
1077 removedApiFile := ctx.ExpandSource(String(d.properties.Check_api.Current.Removed_api_file),
1078 "check_api.current_removed_api_file")
1079
1080 ctx.Build(pctx, android.BuildParams{
1081 Rule: apiCheck,
1082 Description: "Current API check",
1083 Output: d.checkCurrentApiTimestamp,
1084 Inputs: nil,
1085 Implicits: append(android.Paths{apiFile, removedApiFile, d.apiFile, d.removedApiFile},
1086 checkApiClasspath...),
1087 Args: map[string]string{
1088 "classpath": checkApiClasspath.FormJavaClassPath(""),
1089 "opts": String(d.properties.Check_api.Current.Args),
1090 "apiFile": apiFile.String(),
1091 "apiFileToCheck": d.apiFile.String(),
1092 "removedApiFile": removedApiFile.String(),
1093 "removedApiFileToCheck": d.removedApiFile.String(),
1094 "msg": fmt.Sprintf(`\n******************************\n`+
1095 `You have tried to change the API from what has been previously approved.\n\n`+
1096 `To make these errors go away, you have two choices:\n`+
1097 ` 1. You can add '@hide' javadoc comments to the methods, etc. listed in the\n`+
1098 ` errors above.\n\n`+
Jiyong Parkeeb8a642018-05-12 22:21:20 +09001099 ` 2. You can update current.txt by executing the following command:\n`+
Nan Zhang61819ce2018-05-04 18:49:16 -07001100 ` make %s-update-current-api\n\n`+
Jiyong Parkeeb8a642018-05-12 22:21:20 +09001101 ` To submit the revised current.txt to the main Android repository,\n`+
Nan Zhang61819ce2018-05-04 18:49:16 -07001102 ` you will need approval.\n`+
1103 `******************************\n`, ctx.ModuleName()),
1104 },
1105 })
1106
1107 d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, "update_current_api.timestamp")
Nan Zhang61819ce2018-05-04 18:49:16 -07001108 ctx.Build(pctx, android.BuildParams{
1109 Rule: updateApi,
1110 Description: "update current API",
1111 Output: d.updateCurrentApiTimestamp,
1112 Implicits: append(android.Paths{}, apiFile, removedApiFile, d.apiFile, d.removedApiFile),
1113 Args: map[string]string{
1114 "apiFile": apiFile.String(),
1115 "apiFileToCheck": d.apiFile.String(),
1116 "removedApiFile": removedApiFile.String(),
1117 "removedApiFileToCheck": d.removedApiFile.String(),
1118 },
1119 })
1120 }
Nan Zhanga40da042018-08-01 12:48:00 -07001121
Nan Zhang61819ce2018-05-04 18:49:16 -07001122 if d.checkLastReleasedApi() && !ctx.Config().IsPdkBuild() {
1123 d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, "check_last_released_api.timestamp")
1124
1125 apiFile := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Api_file),
1126 "check_api.last_released.api_file")
1127 removedApiFile := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Removed_api_file),
1128 "check_api.last_released.removed_api_file")
1129
1130 ctx.Build(pctx, android.BuildParams{
1131 Rule: apiCheck,
1132 Description: "Last Released API check",
1133 Output: d.checkLastReleasedApiTimestamp,
1134 Inputs: nil,
1135 Implicits: append(android.Paths{apiFile, removedApiFile, d.apiFile, d.removedApiFile},
1136 checkApiClasspath...),
1137 Args: map[string]string{
1138 "classpath": checkApiClasspath.FormJavaClassPath(""),
1139 "opts": String(d.properties.Check_api.Last_released.Args),
1140 "apiFile": apiFile.String(),
1141 "apiFileToCheck": d.apiFile.String(),
1142 "removedApiFile": removedApiFile.String(),
1143 "removedApiFileToCheck": d.removedApiFile.String(),
1144 "msg": `\n******************************\n` +
1145 `You have tried to change the API from what has been previously released in\n` +
1146 `an SDK. Please fix the errors listed above.\n` +
1147 `******************************\n`,
1148 },
1149 })
1150 }
Nan Zhang581fd212018-01-10 16:06:12 -08001151}
Dan Willemsencc090972018-02-26 14:33:31 -08001152
Nan Zhanga40da042018-08-01 12:48:00 -07001153//
Nan Zhangf4936b02018-08-01 15:00:28 -07001154// Exported Droiddoc Directory
Nan Zhanga40da042018-08-01 12:48:00 -07001155//
Dan Willemsencc090972018-02-26 14:33:31 -08001156var droiddocTemplateTag = dependencyTag{name: "droiddoc-template"}
Nan Zhangf4936b02018-08-01 15:00:28 -07001157var metalavaMergeAnnotationsDirTag = dependencyTag{name: "metalava-merge-annotations-dir"}
Dan Willemsencc090972018-02-26 14:33:31 -08001158
Nan Zhangf4936b02018-08-01 15:00:28 -07001159type ExportedDroiddocDirProperties struct {
1160 // path to the directory containing Droiddoc related files.
Dan Willemsencc090972018-02-26 14:33:31 -08001161 Path *string
1162}
1163
Nan Zhangf4936b02018-08-01 15:00:28 -07001164type ExportedDroiddocDir struct {
Dan Willemsencc090972018-02-26 14:33:31 -08001165 android.ModuleBase
1166
Nan Zhangf4936b02018-08-01 15:00:28 -07001167 properties ExportedDroiddocDirProperties
Dan Willemsencc090972018-02-26 14:33:31 -08001168
1169 deps android.Paths
1170 dir android.Path
1171}
1172
Nan Zhangf4936b02018-08-01 15:00:28 -07001173func ExportedDroiddocDirFactory() android.Module {
1174 module := &ExportedDroiddocDir{}
Dan Willemsencc090972018-02-26 14:33:31 -08001175 module.AddProperties(&module.properties)
1176 android.InitAndroidModule(module)
1177 return module
1178}
1179
Nan Zhangf4936b02018-08-01 15:00:28 -07001180func (d *ExportedDroiddocDir) DepsMutator(android.BottomUpMutatorContext) {}
Dan Willemsencc090972018-02-26 14:33:31 -08001181
Nan Zhangf4936b02018-08-01 15:00:28 -07001182func (d *ExportedDroiddocDir) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Dan Willemsencc090972018-02-26 14:33:31 -08001183 path := android.PathForModuleSrc(ctx, String(d.properties.Path))
1184 d.dir = path
1185 d.deps = ctx.Glob(path.Join(ctx, "**/*").String(), nil)
1186}
Nan Zhangb2b33de2018-02-23 11:18:47 -08001187
1188//
1189// Defaults
1190//
1191type DocDefaults struct {
1192 android.ModuleBase
1193 android.DefaultsModuleBase
1194}
1195
1196func (*DocDefaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1197}
1198
1199func (d *DocDefaults) DepsMutator(ctx android.BottomUpMutatorContext) {
1200}
1201
1202func DocDefaultsFactory() android.Module {
1203 module := &DocDefaults{}
1204
1205 module.AddProperties(
1206 &JavadocProperties{},
1207 &DroiddocProperties{},
1208 )
1209
1210 android.InitDefaultsModule(module)
1211
1212 return module
1213}