blob: 202f22bc8a74d755ff2af4f22280f7e6289dc688 [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 Zhang581fd212018-01-10 16:06:12 -080022 "strings"
23
24 "github.com/google/blueprint"
25)
26
27var (
28 javadoc = pctx.AndroidStaticRule("javadoc",
29 blueprint.RuleParams{
30 Command: `rm -rf "$outDir" "$srcJarDir" "$stubsDir" && mkdir -p "$outDir" "$srcJarDir" "$stubsDir" && ` +
Colin Cross436b7652018-03-15 16:24:10 -070031 `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
Nan Zhang581fd212018-01-10 16:06:12 -080032 `${config.JavadocCmd} -encoding UTF-8 @$out.rsp @$srcJarDir/list ` +
33 `$opts $bootclasspathArgs $classpathArgs -sourcepath $sourcepath ` +
34 `-d $outDir -quiet && ` +
35 `${config.SoongZipCmd} -write_if_changed -d -o $docZip -C $outDir -D $outDir && ` +
36 `${config.SoongZipCmd} -write_if_changed -jar -o $out -C $stubsDir -D $stubsDir`,
37 CommandDeps: []string{
Colin Cross436b7652018-03-15 16:24:10 -070038 "${config.ZipSyncCmd}",
Nan Zhang581fd212018-01-10 16:06:12 -080039 "${config.JavadocCmd}",
40 "${config.SoongZipCmd}",
Nan Zhang581fd212018-01-10 16:06:12 -080041 },
42 Rspfile: "$out.rsp",
43 RspfileContent: "$in",
44 Restat: true,
45 },
46 "outDir", "srcJarDir", "stubsDir", "srcJars", "opts",
Nan Zhang30963742018-04-23 09:59:14 -070047 "bootclasspathArgs", "classpathArgs", "sourcepath", "docZip")
Nan Zhang61819ce2018-05-04 18:49:16 -070048
49 apiCheck = pctx.AndroidStaticRule("apiCheck",
50 blueprint.RuleParams{
51 Command: `( ${config.ApiCheckCmd} -JXmx1024m -J"classpath $classpath" $opts ` +
52 `$apiFile $apiFileToCheck $removedApiFile $removedApiFileToCheck ` +
53 `&& touch $out ) || (echo $msg ; exit 38)`,
54 CommandDeps: []string{
55 "${config.ApiCheckCmd}",
56 },
57 },
58 "classpath", "opts", "apiFile", "apiFileToCheck", "removedApiFile", "removedApiFileToCheck", "msg")
59
60 updateApi = pctx.AndroidStaticRule("updateApi",
61 blueprint.RuleParams{
62 Command: `( ( cp -f $apiFileToCheck $apiFile && cp -f $removedApiFileToCheck $removedApiFile ) ` +
63 `&& touch $out ) || (echo failed to update public API ; exit 38)`,
64 },
65 "apiFile", "apiFileToCheck", "removedApiFile", "removedApiFileToCheck")
Nan Zhang581fd212018-01-10 16:06:12 -080066)
67
68func init() {
Nan Zhangb2b33de2018-02-23 11:18:47 -080069 android.RegisterModuleType("doc_defaults", DocDefaultsFactory)
70
Nan Zhang581fd212018-01-10 16:06:12 -080071 android.RegisterModuleType("droiddoc", DroiddocFactory)
72 android.RegisterModuleType("droiddoc_host", DroiddocHostFactory)
Dan Willemsencc090972018-02-26 14:33:31 -080073 android.RegisterModuleType("droiddoc_template", DroiddocTemplateFactory)
Nan Zhang581fd212018-01-10 16:06:12 -080074 android.RegisterModuleType("javadoc", JavadocFactory)
75 android.RegisterModuleType("javadoc_host", JavadocHostFactory)
76}
77
78type JavadocProperties struct {
79 // list of source files used to compile the Java module. May be .java, .logtags, .proto,
80 // or .aidl files.
81 Srcs []string `android:"arch_variant"`
82
83 // list of directories rooted at the Android.bp file that will
84 // be added to the search paths for finding source files when passing package names.
Nan Zhangb2b33de2018-02-23 11:18:47 -080085 Local_sourcepaths []string
Nan Zhang581fd212018-01-10 16:06:12 -080086
87 // list of source files that should not be used to build the Java module.
88 // This is most useful in the arch/multilib variants to remove non-common files
89 // filegroup or genrule can be included within this property.
90 Exclude_srcs []string `android:"arch_variant"`
91
Nan Zhangb2b33de2018-02-23 11:18:47 -080092 // list of java libraries that will be in the classpath.
Nan Zhang581fd212018-01-10 16:06:12 -080093 Libs []string `android:"arch_variant"`
94
Nan Zhange66c7272018-03-06 12:59:27 -080095 // don't build against the framework libraries (legacy-test, core-junit,
96 // ext, and framework for device targets)
97 No_framework_libs *bool
98
Nan Zhangb2b33de2018-02-23 11:18:47 -080099 // the java library (in classpath) for documentation that provides java srcs and srcjars.
100 Srcs_lib *string
101
102 // the base dirs under srcs_lib will be scanned for java srcs.
103 Srcs_lib_whitelist_dirs []string
104
105 // the sub dirs under srcs_lib_whitelist_dirs will be scanned for java srcs.
106 Srcs_lib_whitelist_pkgs []string
107
Nan Zhang581fd212018-01-10 16:06:12 -0800108 // If set to false, don't allow this module(-docs.zip) to be exported. Defaults to true.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800109 Installable *bool
Nan Zhang581fd212018-01-10 16:06:12 -0800110
111 // if not blank, set to the version of the sdk to compile against
112 Sdk_version *string `android:"arch_variant"`
113}
114
Nan Zhang61819ce2018-05-04 18:49:16 -0700115type ApiToCheck struct {
116 Api_file *string
117
118 Removed_api_file *string
119
120 Args *string
121}
122
Nan Zhang581fd212018-01-10 16:06:12 -0800123type DroiddocProperties struct {
124 // directory relative to top of the source tree that contains doc templates files.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800125 Custom_template *string
Nan Zhang581fd212018-01-10 16:06:12 -0800126
127 // directories relative to top of the source tree which contains html/jd files.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800128 Html_dirs []string
Nan Zhang581fd212018-01-10 16:06:12 -0800129
130 // set a value in the Clearsilver hdf namespace.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800131 Hdf []string
Nan Zhang581fd212018-01-10 16:06:12 -0800132
133 // proofread file contains all of the text content of the javadocs concatenated into one file,
134 // suitable for spell-checking and other goodness.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800135 Proofread_file *string
Nan Zhang581fd212018-01-10 16:06:12 -0800136
137 // a todo file lists the program elements that are missing documentation.
138 // At some point, this might be improved to show more warnings.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800139 Todo_file *string
140
141 // directory under current module source that provide additional resources (images).
142 Resourcesdir *string
143
144 // resources output directory under out/soong/.intermediates.
145 Resourcesoutdir *string
Nan Zhang581fd212018-01-10 16:06:12 -0800146
147 // local files that are used within user customized droiddoc options.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800148 Arg_files []string
Nan Zhang581fd212018-01-10 16:06:12 -0800149
150 // user customized droiddoc args.
151 // Available variables for substitution:
152 //
153 // $(location <label>): the path to the arg_files with name <label>
Nan Zhangb2b33de2018-02-23 11:18:47 -0800154 Args *string
Nan Zhang581fd212018-01-10 16:06:12 -0800155
156 // names of the output files used in args that will be generated
Nan Zhangb2b33de2018-02-23 11:18:47 -0800157 Out []string
Nan Zhang581fd212018-01-10 16:06:12 -0800158
159 // a list of files under current module source dir which contains known tags in Java sources.
160 // filegroup or genrule can be included within this property.
Nan Zhangb2b33de2018-02-23 11:18:47 -0800161 Knowntags []string
Nan Zhang28c68b92018-03-13 16:17:01 -0700162
163 // the tag name used to distinguish if the API files belong to public/system/test.
164 Api_tag_name *string
165
166 // the generated public API filename by Doclava.
167 Api_filename *string
168
169 // the generated private API filename by Doclava.
170 Private_api_filename *string
171
172 // the generated private Dex API filename by Doclava.
173 Private_dex_api_filename *string
174
175 // the generated removed API filename by Doclava.
176 Removed_api_filename *string
177
David Brazdilaac0c3c2018-04-24 16:23:29 +0100178 // the generated removed Dex API filename by Doclava.
179 Removed_dex_api_filename *string
180
Nan Zhang28c68b92018-03-13 16:17:01 -0700181 // the generated exact API filename by Doclava.
182 Exact_api_filename *string
Nan Zhang853f4202018-04-12 16:55:56 -0700183
184 // if set to false, don't allow droiddoc to generate stubs source files. Defaults to true.
185 Create_stubs *bool
Nan Zhang61819ce2018-05-04 18:49:16 -0700186
187 Check_api struct {
188 Last_released ApiToCheck
189
190 Current ApiToCheck
191 }
Nan Zhang581fd212018-01-10 16:06:12 -0800192}
193
194type Javadoc struct {
195 android.ModuleBase
196 android.DefaultableModuleBase
197
198 properties JavadocProperties
199
200 srcJars android.Paths
201 srcFiles android.Paths
202 sourcepaths android.Paths
203
Nan Zhangccff0f72018-03-08 17:26:16 -0800204 docZip android.WritablePath
205 stubsSrcJar android.WritablePath
Nan Zhang581fd212018-01-10 16:06:12 -0800206}
207
Nan Zhangb2b33de2018-02-23 11:18:47 -0800208func (j *Javadoc) Srcs() android.Paths {
209 return android.Paths{j.stubsSrcJar}
210}
211
212var _ android.SourceFileProducer = (*Javadoc)(nil)
213
Nan Zhang581fd212018-01-10 16:06:12 -0800214type Droiddoc struct {
215 Javadoc
216
Nan Zhang28c68b92018-03-13 16:17:01 -0700217 properties DroiddocProperties
218 apiFile android.WritablePath
219 privateApiFile android.WritablePath
220 privateDexApiFile android.WritablePath
221 removedApiFile android.WritablePath
David Brazdilaac0c3c2018-04-24 16:23:29 +0100222 removedDexApiFile android.WritablePath
Nan Zhang28c68b92018-03-13 16:17:01 -0700223 exactApiFile android.WritablePath
Nan Zhang61819ce2018-05-04 18:49:16 -0700224
225 checkCurrentApiTimestamp android.WritablePath
226 updateCurrentApiTimestamp android.WritablePath
227 checkLastReleasedApiTimestamp android.WritablePath
Nan Zhang581fd212018-01-10 16:06:12 -0800228}
229
230func InitDroiddocModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
231 android.InitAndroidArchModule(module, hod, android.MultilibCommon)
232 android.InitDefaultableModule(module)
233}
234
235func JavadocFactory() android.Module {
236 module := &Javadoc{}
237
238 module.AddProperties(&module.properties)
239
240 InitDroiddocModule(module, android.HostAndDeviceSupported)
241 return module
242}
243
244func JavadocHostFactory() android.Module {
245 module := &Javadoc{}
246
247 module.AddProperties(&module.properties)
248
249 InitDroiddocModule(module, android.HostSupported)
250 return module
251}
252
253func DroiddocFactory() android.Module {
254 module := &Droiddoc{}
255
256 module.AddProperties(&module.properties,
257 &module.Javadoc.properties)
258
259 InitDroiddocModule(module, android.HostAndDeviceSupported)
260 return module
261}
262
263func DroiddocHostFactory() android.Module {
264 module := &Droiddoc{}
265
266 module.AddProperties(&module.properties,
267 &module.Javadoc.properties)
268
269 InitDroiddocModule(module, android.HostSupported)
270 return module
271}
272
273func (j *Javadoc) addDeps(ctx android.BottomUpMutatorContext) {
274 if ctx.Device() {
275 sdkDep := decodeSdkDep(ctx, String(j.properties.Sdk_version))
276 if sdkDep.useDefaultLibs {
277 ctx.AddDependency(ctx.Module(), bootClasspathTag, config.DefaultBootclasspathLibraries...)
Nan Zhang9cbe6772018-03-21 17:56:39 -0700278 if !Bool(j.properties.No_framework_libs) {
Nan Zhange66c7272018-03-06 12:59:27 -0800279 ctx.AddDependency(ctx.Module(), libTag, []string{"ext", "framework"}...)
280 }
Nan Zhang581fd212018-01-10 16:06:12 -0800281 } else if sdkDep.useModule {
282 ctx.AddDependency(ctx.Module(), bootClasspathTag, sdkDep.module)
283 }
284 }
285
286 ctx.AddDependency(ctx.Module(), libTag, j.properties.Libs...)
287
288 android.ExtractSourcesDeps(ctx, j.properties.Srcs)
289
290 // exclude_srcs may contain filegroup or genrule.
291 android.ExtractSourcesDeps(ctx, j.properties.Exclude_srcs)
292}
293
Nan Zhangb2b33de2018-02-23 11:18:47 -0800294func (j *Javadoc) genWhitelistPathPrefixes(whitelistPathPrefixes map[string]bool) {
295 for _, dir := range j.properties.Srcs_lib_whitelist_dirs {
296 for _, pkg := range j.properties.Srcs_lib_whitelist_pkgs {
Jiyong Park82484c02018-04-23 21:41:26 +0900297 // convert foo.bar.baz to foo/bar/baz
298 pkgAsPath := filepath.Join(strings.Split(pkg, ".")...)
299 prefix := filepath.Join(dir, pkgAsPath)
Nan Zhangb2b33de2018-02-23 11:18:47 -0800300 if _, found := whitelistPathPrefixes[prefix]; !found {
301 whitelistPathPrefixes[prefix] = true
302 }
303 }
304 }
305}
306
Nan Zhang581fd212018-01-10 16:06:12 -0800307func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps {
308 var deps deps
309
310 sdkDep := decodeSdkDep(ctx, String(j.properties.Sdk_version))
311 if sdkDep.invalidVersion {
312 ctx.AddMissingDependencies([]string{sdkDep.module})
313 } else if sdkDep.useFiles {
314 deps.bootClasspath = append(deps.bootClasspath, sdkDep.jar)
315 }
316
317 ctx.VisitDirectDeps(func(module android.Module) {
318 otherName := ctx.OtherModuleName(module)
319 tag := ctx.OtherModuleDependencyTag(module)
320
321 switch dep := module.(type) {
322 case Dependency:
323 switch tag {
324 case bootClasspathTag:
325 deps.bootClasspath = append(deps.bootClasspath, dep.ImplementationJars()...)
326 case libTag:
327 deps.classpath = append(deps.classpath, dep.ImplementationJars()...)
Nan Zhangb2b33de2018-02-23 11:18:47 -0800328 if otherName == String(j.properties.Srcs_lib) {
329 srcs := dep.(SrcDependency).CompiledSrcs()
330 whitelistPathPrefixes := make(map[string]bool)
331 j.genWhitelistPathPrefixes(whitelistPathPrefixes)
332 for _, src := range srcs {
333 if _, ok := src.(android.WritablePath); ok { // generated sources
334 deps.srcs = append(deps.srcs, src)
335 } else { // select source path for documentation based on whitelist path prefixs.
336 for k, _ := range whitelistPathPrefixes {
337 if strings.HasPrefix(src.Rel(), k) {
338 deps.srcs = append(deps.srcs, src)
339 break
340 }
341 }
342 }
343 }
344 deps.srcJars = append(deps.srcJars, dep.(SrcDependency).CompiledSrcJars()...)
345 }
Nan Zhang581fd212018-01-10 16:06:12 -0800346 default:
347 panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
348 }
Jiyong Parkc678ad32018-04-10 13:07:10 +0900349 case SdkLibraryDependency:
350 switch tag {
351 case libTag:
352 sdkVersion := String(j.properties.Sdk_version)
353 linkType := javaSdk
354 if strings.HasPrefix(sdkVersion, "system_") || strings.HasPrefix(sdkVersion, "test_") {
355 linkType = javaSystem
356 } else if sdkVersion == "" {
357 linkType = javaPlatform
358 }
359 deps.classpath = append(deps.classpath, dep.HeaderJars(linkType)...)
360 default:
361 ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
362 }
Nan Zhang581fd212018-01-10 16:06:12 -0800363 case android.SourceFileProducer:
364 switch tag {
365 case libTag:
366 checkProducesJars(ctx, dep)
367 deps.classpath = append(deps.classpath, dep.Srcs()...)
368 case android.DefaultsDepTag, android.SourceDepTag:
369 // Nothing to do
370 default:
371 ctx.ModuleErrorf("dependency on genrule %q may only be in srcs, libs", otherName)
372 }
373 default:
374 switch tag {
Dan Willemsencc090972018-02-26 14:33:31 -0800375 case android.DefaultsDepTag, android.SourceDepTag, droiddocTemplateTag:
Nan Zhang581fd212018-01-10 16:06:12 -0800376 // Nothing to do
377 default:
378 ctx.ModuleErrorf("depends on non-java module %q", otherName)
379 }
380 }
381 })
382 // do not pass exclude_srcs directly when expanding srcFiles since exclude_srcs
383 // may contain filegroup or genrule.
384 srcFiles := ctx.ExpandSources(j.properties.Srcs, j.properties.Exclude_srcs)
385
386 // srcs may depend on some genrule output.
387 j.srcJars = srcFiles.FilterByExt(".srcjar")
Nan Zhangb2b33de2018-02-23 11:18:47 -0800388 j.srcJars = append(j.srcJars, deps.srcJars...)
389
Nan Zhang581fd212018-01-10 16:06:12 -0800390 j.srcFiles = srcFiles.FilterOutByExt(".srcjar")
Nan Zhangb2b33de2018-02-23 11:18:47 -0800391 j.srcFiles = append(j.srcFiles, deps.srcs...)
Nan Zhang581fd212018-01-10 16:06:12 -0800392
393 j.docZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"docs.zip")
Nan Zhangccff0f72018-03-08 17:26:16 -0800394 j.stubsSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
Nan Zhang581fd212018-01-10 16:06:12 -0800395
396 if j.properties.Local_sourcepaths == nil {
397 j.properties.Local_sourcepaths = append(j.properties.Local_sourcepaths, ".")
398 }
399 j.sourcepaths = android.PathsForModuleSrc(ctx, j.properties.Local_sourcepaths)
Nan Zhang581fd212018-01-10 16:06:12 -0800400
401 return deps
402}
403
404func (j *Javadoc) DepsMutator(ctx android.BottomUpMutatorContext) {
405 j.addDeps(ctx)
406}
407
408func (j *Javadoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
409 deps := j.collectDeps(ctx)
410
411 var implicits android.Paths
412 implicits = append(implicits, deps.bootClasspath...)
413 implicits = append(implicits, deps.classpath...)
414
415 var bootClasspathArgs, classpathArgs string
416 if ctx.Config().UseOpenJDK9() {
417 if len(deps.bootClasspath) > 0 {
418 // For OpenJDK 9 we use --patch-module to define the core libraries code.
419 // TODO(tobiast): Reorganize this when adding proper support for OpenJDK 9
420 // modules. Here we treat all code in core libraries as being in java.base
421 // to work around the OpenJDK 9 module system. http://b/62049770
422 bootClasspathArgs = "--patch-module=java.base=" + strings.Join(deps.bootClasspath.Strings(), ":")
423 }
424 } else {
425 if len(deps.bootClasspath.Strings()) > 0 {
426 // For OpenJDK 8 we can use -bootclasspath to define the core libraries code.
427 bootClasspathArgs = deps.bootClasspath.FormJavaClassPath("-bootclasspath")
428 }
429 }
430 if len(deps.classpath.Strings()) > 0 {
431 classpathArgs = "-classpath " + strings.Join(deps.classpath.Strings(), ":")
432 }
433
434 implicits = append(implicits, j.srcJars...)
435
436 opts := "-J-Xmx1024m -XDignore.symbol.file -Xdoclint:none"
437
438 ctx.Build(pctx, android.BuildParams{
439 Rule: javadoc,
440 Description: "Javadoc",
Nan Zhangccff0f72018-03-08 17:26:16 -0800441 Output: j.stubsSrcJar,
Nan Zhang581fd212018-01-10 16:06:12 -0800442 ImplicitOutput: j.docZip,
443 Inputs: j.srcFiles,
444 Implicits: implicits,
445 Args: map[string]string{
446 "outDir": android.PathForModuleOut(ctx, "docs", "out").String(),
447 "srcJarDir": android.PathForModuleOut(ctx, "docs", "srcjars").String(),
448 "stubsDir": android.PathForModuleOut(ctx, "docs", "stubsDir").String(),
449 "srcJars": strings.Join(j.srcJars.Strings(), " "),
450 "opts": opts,
Nan Zhang853f4202018-04-12 16:55:56 -0700451 "bootclasspathArgs": bootClasspathArgs,
Nan Zhang581fd212018-01-10 16:06:12 -0800452 "classpathArgs": classpathArgs,
453 "sourcepath": strings.Join(j.sourcepaths.Strings(), ":"),
454 "docZip": j.docZip.String(),
455 },
456 })
457}
458
Nan Zhang61819ce2018-05-04 18:49:16 -0700459func (d *Droiddoc) checkCurrentApi() bool {
460 if String(d.properties.Check_api.Current.Api_file) != "" &&
461 String(d.properties.Check_api.Current.Removed_api_file) != "" {
462 return true
463 } else if String(d.properties.Check_api.Current.Api_file) != "" {
464 panic("check_api.current.removed_api_file: has to be non empty!")
465 } else if String(d.properties.Check_api.Current.Removed_api_file) != "" {
466 panic("check_api.current.api_file: has to be non empty!")
467 }
468
469 return false
470}
471
472func (d *Droiddoc) checkLastReleasedApi() bool {
473 if String(d.properties.Check_api.Last_released.Api_file) != "" &&
474 String(d.properties.Check_api.Last_released.Removed_api_file) != "" {
475 return true
476 } else if String(d.properties.Check_api.Last_released.Api_file) != "" {
477 panic("check_api.last_released.removed_api_file: has to be non empty!")
478 } else if String(d.properties.Check_api.Last_released.Removed_api_file) != "" {
479 panic("check_api.last_released.api_file: has to be non empty!")
480 }
481
482 return false
483}
484
Nan Zhang581fd212018-01-10 16:06:12 -0800485func (d *Droiddoc) DepsMutator(ctx android.BottomUpMutatorContext) {
486 d.Javadoc.addDeps(ctx)
487
Dan Willemsencc090972018-02-26 14:33:31 -0800488 if String(d.properties.Custom_template) == "" {
489 // TODO: This is almost always droiddoc-templates-sdk
490 ctx.PropertyErrorf("custom_template", "must specify a template")
491 } else {
492 ctx.AddDependency(ctx.Module(), droiddocTemplateTag, String(d.properties.Custom_template))
493 }
494
Nan Zhang581fd212018-01-10 16:06:12 -0800495 // extra_arg_files may contains filegroup or genrule.
496 android.ExtractSourcesDeps(ctx, d.properties.Arg_files)
497
498 // knowntags may contain filegroup or genrule.
499 android.ExtractSourcesDeps(ctx, d.properties.Knowntags)
Nan Zhang61819ce2018-05-04 18:49:16 -0700500
501 if d.checkCurrentApi() {
502 android.ExtractSourceDeps(ctx, d.properties.Check_api.Current.Api_file)
503 android.ExtractSourceDeps(ctx, d.properties.Check_api.Current.Removed_api_file)
504 }
505
506 if d.checkLastReleasedApi() {
507 android.ExtractSourceDeps(ctx, d.properties.Check_api.Last_released.Api_file)
508 android.ExtractSourceDeps(ctx, d.properties.Check_api.Last_released.Removed_api_file)
509 }
Nan Zhang581fd212018-01-10 16:06:12 -0800510}
511
512func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
513 deps := d.Javadoc.collectDeps(ctx)
514
515 var implicits android.Paths
516 implicits = append(implicits, deps.bootClasspath...)
517 implicits = append(implicits, deps.classpath...)
518
519 argFiles := ctx.ExpandSources(d.properties.Arg_files, nil)
520 argFilesMap := map[string]android.Path{}
521
522 for _, f := range argFiles {
523 implicits = append(implicits, f)
524 if _, exists := argFilesMap[f.Rel()]; !exists {
525 argFilesMap[f.Rel()] = f
526 } else {
527 ctx.ModuleErrorf("multiple arg_files for %q, %q and %q",
528 f, argFilesMap[f.Rel()], f.Rel())
529 }
530 }
531
532 args, err := android.Expand(String(d.properties.Args), func(name string) (string, error) {
533 if strings.HasPrefix(name, "location ") {
534 label := strings.TrimSpace(strings.TrimPrefix(name, "location "))
535 if f, ok := argFilesMap[label]; ok {
536 return f.String(), nil
537 } else {
538 return "", fmt.Errorf("unknown location label %q", label)
539 }
540 } else if name == "genDir" {
541 return android.PathForModuleGen(ctx).String(), nil
542 }
543 return "", fmt.Errorf("unknown variable '$(%s)'", name)
544 })
545
546 if err != nil {
547 ctx.PropertyErrorf("extra_args", "%s", err.Error())
548 return
549 }
550
551 var bootClasspathArgs, classpathArgs string
552 if len(deps.bootClasspath.Strings()) > 0 {
553 bootClasspathArgs = "-bootclasspath " + strings.Join(deps.bootClasspath.Strings(), ":")
554 }
555 if len(deps.classpath.Strings()) > 0 {
556 classpathArgs = "-classpath " + strings.Join(deps.classpath.Strings(), ":")
557 }
558
Dan Willemsencc090972018-02-26 14:33:31 -0800559 var templateDir string
560 ctx.VisitDirectDepsWithTag(droiddocTemplateTag, func(m android.Module) {
561 if t, ok := m.(*DroiddocTemplate); ok {
562 implicits = append(implicits, t.deps...)
563 templateDir = t.dir.String()
564 } else {
565 ctx.PropertyErrorf("custom_template", "module %q is not a droiddoc_template", ctx.OtherModuleName(m))
566 }
567 })
Nan Zhang581fd212018-01-10 16:06:12 -0800568
569 var htmlDirArgs string
570 if len(d.properties.Html_dirs) > 0 {
Dan Willemsencc090972018-02-26 14:33:31 -0800571 htmlDir := android.PathForModuleSrc(ctx, d.properties.Html_dirs[0])
572 implicits = append(implicits, ctx.Glob(htmlDir.Join(ctx, "**/*").String(), nil)...)
573 htmlDirArgs = "-htmldir " + htmlDir.String()
Nan Zhang581fd212018-01-10 16:06:12 -0800574 }
575
576 var htmlDir2Args string
577 if len(d.properties.Html_dirs) > 1 {
Dan Willemsencc090972018-02-26 14:33:31 -0800578 htmlDir2 := android.PathForModuleSrc(ctx, d.properties.Html_dirs[1])
579 implicits = append(implicits, ctx.Glob(htmlDir2.Join(ctx, "**/*").String(), nil)...)
580 htmlDir2Args = "-htmldir2 " + htmlDir2.String()
581 }
582
583 if len(d.properties.Html_dirs) > 2 {
584 ctx.PropertyErrorf("html_dirs", "Droiddoc only supports up to 2 html dirs")
Nan Zhang581fd212018-01-10 16:06:12 -0800585 }
586
587 knownTags := ctx.ExpandSources(d.properties.Knowntags, nil)
588 implicits = append(implicits, knownTags...)
589
590 for _, kt := range knownTags {
591 args = args + " -knowntags " + kt.String()
592 }
593 for _, hdf := range d.properties.Hdf {
594 args = args + " -hdf " + hdf
595 }
596
597 if String(d.properties.Proofread_file) != "" {
598 proofreadFile := android.PathForModuleOut(ctx, String(d.properties.Proofread_file))
599 args = args + " -proofread " + proofreadFile.String()
600 }
Nan Zhangb2b33de2018-02-23 11:18:47 -0800601
Nan Zhang581fd212018-01-10 16:06:12 -0800602 if String(d.properties.Todo_file) != "" {
603 // tricky part:
604 // we should not compute full path for todo_file through PathForModuleOut().
605 // the non-standard doclet will get the full path relative to "-o".
606 args = args + " -todo " + String(d.properties.Todo_file)
607 }
608
Nan Zhangb2b33de2018-02-23 11:18:47 -0800609 if String(d.properties.Resourcesdir) != "" {
610 // TODO: should we add files under resourcesDir to the implicits? It seems that
611 // resourcesDir is one sub dir of htmlDir
612 resourcesDir := android.PathForModuleSrc(ctx, String(d.properties.Resourcesdir))
613 args = args + " -resourcesdir " + resourcesDir.String()
614 }
615
616 if String(d.properties.Resourcesoutdir) != "" {
617 // TODO: it seems -resourceoutdir reference/android/images/ didn't get generated anywhere.
618 args = args + " -resourcesoutdir " + String(d.properties.Resourcesoutdir)
619 }
620
Nan Zhang28c68b92018-03-13 16:17:01 -0700621 var implicitOutputs android.WritablePaths
Nan Zhang61819ce2018-05-04 18:49:16 -0700622
623 if d.checkCurrentApi() || d.checkLastReleasedApi() || String(d.properties.Api_filename) != "" {
624 d.apiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_api.txt")
Nan Zhang28c68b92018-03-13 16:17:01 -0700625 args = args + " -api " + d.apiFile.String()
626 implicitOutputs = append(implicitOutputs, d.apiFile)
627 }
628
Nan Zhang61819ce2018-05-04 18:49:16 -0700629 if d.checkCurrentApi() || d.checkLastReleasedApi() || String(d.properties.Removed_api_filename) != "" {
630 d.removedApiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_removed.txt")
631 args = args + " -removedApi " + d.removedApiFile.String()
632 implicitOutputs = append(implicitOutputs, d.removedApiFile)
633 }
634
Nan Zhang28c68b92018-03-13 16:17:01 -0700635 if String(d.properties.Private_api_filename) != "" {
636 d.privateApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_api_filename))
637 args = args + " -privateApi " + d.privateApiFile.String()
638 implicitOutputs = append(implicitOutputs, d.privateApiFile)
639 }
640
641 if String(d.properties.Private_dex_api_filename) != "" {
642 d.privateDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_dex_api_filename))
643 args = args + " -privateDexApi " + d.privateDexApiFile.String()
644 implicitOutputs = append(implicitOutputs, d.privateDexApiFile)
645 }
646
David Brazdilaac0c3c2018-04-24 16:23:29 +0100647 if String(d.properties.Removed_dex_api_filename) != "" {
648 d.removedDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Removed_dex_api_filename))
649 args = args + " -removedDexApi " + d.removedDexApiFile.String()
650 implicitOutputs = append(implicitOutputs, d.removedDexApiFile)
651 }
652
Nan Zhang28c68b92018-03-13 16:17:01 -0700653 if String(d.properties.Exact_api_filename) != "" {
654 d.exactApiFile = android.PathForModuleOut(ctx, String(d.properties.Exact_api_filename))
655 args = args + " -exactApi " + d.exactApiFile.String()
656 implicitOutputs = append(implicitOutputs, d.exactApiFile)
657 }
658
Nan Zhang581fd212018-01-10 16:06:12 -0800659 implicits = append(implicits, d.Javadoc.srcJars...)
660
Nan Zhang30963742018-04-23 09:59:14 -0700661 jsilver := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "jsilver.jar")
662 doclava := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "doclava.jar")
663 implicits = append(implicits, jsilver)
664 implicits = append(implicits, doclava)
665
Nan Zhang581fd212018-01-10 16:06:12 -0800666 opts := "-source 1.8 -J-Xmx1600m -J-XX:-OmitStackTraceInFastThrow -XDignore.symbol.file " +
Nan Zhang30963742018-04-23 09:59:14 -0700667 "-doclet com.google.doclava.Doclava -docletpath " + jsilver.String() + ":" + doclava.String() + " " +
Colin Cross480cd762018-02-22 14:39:17 -0800668 "-templatedir " + templateDir + " " + htmlDirArgs + " " + htmlDir2Args + " " +
Nan Zhang581fd212018-01-10 16:06:12 -0800669 "-hdf page.build " + ctx.Config().BuildId() + "-" + ctx.Config().BuildNumberFromFile() + " " +
Nan Zhang853f4202018-04-12 16:55:56 -0700670 "-hdf page.now " + `"$$(date -d @$$(cat ` + ctx.Config().Getenv("BUILD_DATETIME_FILE") + `) "+%d %b %Y %k:%M")"` +
671 " " + args
672 if BoolDefault(d.properties.Create_stubs, true) {
673 opts += " -stubs " + android.PathForModuleOut(ctx, "docs", "stubsDir").String()
674 }
Nan Zhang581fd212018-01-10 16:06:12 -0800675
Nan Zhang581fd212018-01-10 16:06:12 -0800676 implicitOutputs = append(implicitOutputs, d.Javadoc.docZip)
677 for _, o := range d.properties.Out {
678 implicitOutputs = append(implicitOutputs, android.PathForModuleGen(ctx, o))
679 }
680
681 ctx.Build(pctx, android.BuildParams{
682 Rule: javadoc,
683 Description: "Droiddoc",
Nan Zhangccff0f72018-03-08 17:26:16 -0800684 Output: d.Javadoc.stubsSrcJar,
Nan Zhang581fd212018-01-10 16:06:12 -0800685 Inputs: d.Javadoc.srcFiles,
686 Implicits: implicits,
687 ImplicitOutputs: implicitOutputs,
688 Args: map[string]string{
689 "outDir": android.PathForModuleOut(ctx, "docs", "out").String(),
690 "srcJarDir": android.PathForModuleOut(ctx, "docs", "srcjars").String(),
691 "stubsDir": android.PathForModuleOut(ctx, "docs", "stubsDir").String(),
692 "srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "),
693 "opts": opts,
694 "bootclasspathArgs": bootClasspathArgs,
695 "classpathArgs": classpathArgs,
696 "sourcepath": strings.Join(d.Javadoc.sourcepaths.Strings(), ":"),
697 "docZip": d.Javadoc.docZip.String(),
Nan Zhang581fd212018-01-10 16:06:12 -0800698 },
699 })
Nan Zhang61819ce2018-05-04 18:49:16 -0700700
701 java8Home := ctx.Config().Getenv("ANDROID_JAVA8_HOME")
702
703 checkApiClasspath := classpath{jsilver, doclava, android.PathForSource(ctx, java8Home, "lib/tools.jar")}
704
705 if d.checkCurrentApi() && !ctx.Config().IsPdkBuild() {
706 d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, "check_current_api.timestamp")
707
708 apiFile := ctx.ExpandSource(String(d.properties.Check_api.Current.Api_file),
709 "check_api.current.api_file")
710 removedApiFile := ctx.ExpandSource(String(d.properties.Check_api.Current.Removed_api_file),
711 "check_api.current_removed_api_file")
712
713 ctx.Build(pctx, android.BuildParams{
714 Rule: apiCheck,
715 Description: "Current API check",
716 Output: d.checkCurrentApiTimestamp,
717 Inputs: nil,
718 Implicits: append(android.Paths{apiFile, removedApiFile, d.apiFile, d.removedApiFile},
719 checkApiClasspath...),
720 Args: map[string]string{
721 "classpath": checkApiClasspath.FormJavaClassPath(""),
722 "opts": String(d.properties.Check_api.Current.Args),
723 "apiFile": apiFile.String(),
724 "apiFileToCheck": d.apiFile.String(),
725 "removedApiFile": removedApiFile.String(),
726 "removedApiFileToCheck": d.removedApiFile.String(),
727 "msg": fmt.Sprintf(`\n******************************\n`+
728 `You have tried to change the API from what has been previously approved.\n\n`+
729 `To make these errors go away, you have two choices:\n`+
730 ` 1. You can add '@hide' javadoc comments to the methods, etc. listed in the\n`+
731 ` errors above.\n\n`+
732 ` 2. You can update current.txt by executing the following command:`+
733 ` make %s-update-current-api\n\n`+
734 ` To submit the revised current.txt to the main Android repository,`+
735 ` you will need approval.\n`+
736 `******************************\n`, ctx.ModuleName()),
737 },
738 })
739
740 d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, "update_current_api.timestamp")
741
742 ctx.Build(pctx, android.BuildParams{
743 Rule: updateApi,
744 Description: "update current API",
745 Output: d.updateCurrentApiTimestamp,
746 Implicits: append(android.Paths{}, apiFile, removedApiFile, d.apiFile, d.removedApiFile),
747 Args: map[string]string{
748 "apiFile": apiFile.String(),
749 "apiFileToCheck": d.apiFile.String(),
750 "removedApiFile": removedApiFile.String(),
751 "removedApiFileToCheck": d.removedApiFile.String(),
752 },
753 })
754 }
755
756 if d.checkLastReleasedApi() && !ctx.Config().IsPdkBuild() {
757 d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, "check_last_released_api.timestamp")
758
759 apiFile := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Api_file),
760 "check_api.last_released.api_file")
761 removedApiFile := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Removed_api_file),
762 "check_api.last_released.removed_api_file")
763
764 ctx.Build(pctx, android.BuildParams{
765 Rule: apiCheck,
766 Description: "Last Released API check",
767 Output: d.checkLastReleasedApiTimestamp,
768 Inputs: nil,
769 Implicits: append(android.Paths{apiFile, removedApiFile, d.apiFile, d.removedApiFile},
770 checkApiClasspath...),
771 Args: map[string]string{
772 "classpath": checkApiClasspath.FormJavaClassPath(""),
773 "opts": String(d.properties.Check_api.Last_released.Args),
774 "apiFile": apiFile.String(),
775 "apiFileToCheck": d.apiFile.String(),
776 "removedApiFile": removedApiFile.String(),
777 "removedApiFileToCheck": d.removedApiFile.String(),
778 "msg": `\n******************************\n` +
779 `You have tried to change the API from what has been previously released in\n` +
780 `an SDK. Please fix the errors listed above.\n` +
781 `******************************\n`,
782 },
783 })
784 }
Nan Zhang581fd212018-01-10 16:06:12 -0800785}
Dan Willemsencc090972018-02-26 14:33:31 -0800786
787var droiddocTemplateTag = dependencyTag{name: "droiddoc-template"}
788
789type DroiddocTemplateProperties struct {
790 // path to the directory containing the droiddoc templates.
791 Path *string
792}
793
794type DroiddocTemplate struct {
795 android.ModuleBase
796
797 properties DroiddocTemplateProperties
798
799 deps android.Paths
800 dir android.Path
801}
802
803func DroiddocTemplateFactory() android.Module {
804 module := &DroiddocTemplate{}
805 module.AddProperties(&module.properties)
806 android.InitAndroidModule(module)
807 return module
808}
809
810func (d *DroiddocTemplate) DepsMutator(android.BottomUpMutatorContext) {}
811
812func (d *DroiddocTemplate) GenerateAndroidBuildActions(ctx android.ModuleContext) {
813 path := android.PathForModuleSrc(ctx, String(d.properties.Path))
814 d.dir = path
815 d.deps = ctx.Glob(path.Join(ctx, "**/*").String(), nil)
816}
Nan Zhangb2b33de2018-02-23 11:18:47 -0800817
818//
819// Defaults
820//
821type DocDefaults struct {
822 android.ModuleBase
823 android.DefaultsModuleBase
824}
825
826func (*DocDefaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
827}
828
829func (d *DocDefaults) DepsMutator(ctx android.BottomUpMutatorContext) {
830}
831
832func DocDefaultsFactory() android.Module {
833 module := &DocDefaults{}
834
835 module.AddProperties(
836 &JavadocProperties{},
837 &DroiddocProperties{},
838 )
839
840 android.InitDefaultsModule(module)
841
842 return module
843}