1// Copyright 2018 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package java 16 17import ( 18 "android/soong/android" 19 "android/soong/java/config" 20 "fmt" 21 "path/filepath" 22 "runtime" 23 "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" && ` + 32 `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` + 33 `${config.SoongJavacWrapper} ${config.JavadocCmd} -encoding UTF-8 @$out.rsp @$srcJarDir/list ` + 34 `$opts $bootclasspathArgs $classpathArgs $sourcepathArgs ` + 35 `-d $outDir -quiet && ` + 36 `${config.SoongZipCmd} -write_if_changed -d -o $docZip -C $outDir -D $outDir && ` + 37 `${config.SoongZipCmd} -write_if_changed -jar -o $out -C $stubsDir -D $stubsDir $postDoclavaCmds && ` + 38 `rm -rf "$srcJarDir"`, 39 40 CommandDeps: []string{ 41 "${config.ZipSyncCmd}", 42 "${config.JavadocCmd}", 43 "${config.SoongZipCmd}", 44 }, 45 CommandOrderOnly: []string{"${config.SoongJavacWrapper}"}, 46 Rspfile: "$out.rsp", 47 RspfileContent: "$in", 48 Restat: true, 49 }, 50 "outDir", "srcJarDir", "stubsDir", "srcJars", "opts", 51 "bootclasspathArgs", "classpathArgs", "sourcepathArgs", "docZip", "postDoclavaCmds") 52 53 apiCheck = pctx.AndroidStaticRule("apiCheck", 54 blueprint.RuleParams{ 55 Command: `( ${config.ApiCheckCmd} -JXmx1024m -J"classpath $classpath" $opts ` + 56 `$apiFile $apiFileToCheck $removedApiFile $removedApiFileToCheck ` + 57 `&& touch $out ) || (echo -e "$msg" ; exit 38)`, 58 CommandDeps: []string{ 59 "${config.ApiCheckCmd}", 60 }, 61 }, 62 "classpath", "opts", "apiFile", "apiFileToCheck", "removedApiFile", "removedApiFileToCheck", "msg") 63 64 updateApi = pctx.AndroidStaticRule("updateApi", 65 blueprint.RuleParams{ 66 Command: `( ( cp -f $srcApiFile $destApiFile && cp -f $srcRemovedApiFile $destRemovedApiFile ) ` + 67 `&& touch $out ) || (echo failed to update public API ; exit 38)`, 68 }, 69 "srcApiFile", "destApiFile", "srcRemovedApiFile", "destRemovedApiFile") 70 71 metalava = pctx.AndroidStaticRule("metalava", 72 blueprint.RuleParams{ 73 Command: `rm -rf "$outDir" "$srcJarDir" "$stubsDir" && ` + 74 `mkdir -p "$outDir" "$srcJarDir" "$stubsDir" && ` + 75 `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` + 76 `${config.JavaCmd} -jar ${config.MetalavaJar} -encoding UTF-8 -source $javaVersion @$out.rsp @$srcJarDir/list ` + 77 `$bootclasspathArgs $classpathArgs $sourcepathArgs --no-banner --color --quiet --format=v2 ` + 78 `$opts && ` + 79 `${config.SoongZipCmd} -write_if_changed -jar -o $out -C $stubsDir -D $stubsDir && ` + 80 `rm -rf "$srcJarDir"`, 81 CommandDeps: []string{ 82 "${config.ZipSyncCmd}", 83 "${config.JavaCmd}", 84 "${config.MetalavaJar}", 85 "${config.SoongZipCmd}", 86 }, 87 Rspfile: "$out.rsp", 88 RspfileContent: "$in", 89 Restat: true, 90 }, 91 "outDir", "srcJarDir", "stubsDir", "srcJars", "javaVersion", "bootclasspathArgs", 92 "classpathArgs", "sourcepathArgs", "opts") 93 94 metalavaApiCheck = pctx.AndroidStaticRule("metalavaApiCheck", 95 blueprint.RuleParams{ 96 Command: `( rm -rf "$srcJarDir" && mkdir -p "$srcJarDir" && ` + 97 `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` + 98 `${config.JavaCmd} -jar ${config.MetalavaJar} -encoding UTF-8 -source $javaVersion @$out.rsp @$srcJarDir/list ` + 99 `$bootclasspathArgs $classpathArgs $sourcepathArgs --no-banner --color --quiet --format=v2 ` + 100 `$opts && touch $out && rm -rf "$srcJarDir") || ` + 101 `( echo -e "$msg" ; exit 38 )`, 102 CommandDeps: []string{ 103 "${config.ZipSyncCmd}", 104 "${config.JavaCmd}", 105 "${config.MetalavaJar}", 106 }, 107 Rspfile: "$out.rsp", 108 RspfileContent: "$in", 109 }, 110 "srcJarDir", "srcJars", "javaVersion", "bootclasspathArgs", "classpathArgs", "sourcepathArgs", "opts", "msg") 111 112 nullabilityWarningsCheck = pctx.AndroidStaticRule("nullabilityWarningsCheck", 113 blueprint.RuleParams{ 114 Command: `( diff $expected $actual && touch $out ) || ( echo -e "$msg" ; exit 38 )`, 115 }, 116 "expected", "actual", "msg") 117 118 dokka = pctx.AndroidStaticRule("dokka", 119 blueprint.RuleParams{ 120 Command: `rm -rf "$outDir" "$srcJarDir" "$stubsDir" && ` + 121 `mkdir -p "$outDir" "$srcJarDir" "$stubsDir" && ` + 122 `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` + 123 `${config.JavaCmd} -jar ${config.DokkaJar} $srcJarDir ` + 124 `$classpathArgs -format dac -dacRoot /reference/kotlin -output $outDir $opts && ` + 125 `${config.SoongZipCmd} -write_if_changed -d -o $docZip -C $outDir -D $outDir && ` + 126 `${config.SoongZipCmd} -write_if_changed -jar -o $out -C $stubsDir -D $stubsDir && ` + 127 `rm -rf "$srcJarDir"`, 128 CommandDeps: []string{ 129 "${config.ZipSyncCmd}", 130 "${config.DokkaJar}", 131 "${config.MetalavaJar}", 132 "${config.SoongZipCmd}", 133 }, 134 Restat: true, 135 }, 136 "outDir", "srcJarDir", "stubsDir", "srcJars", "classpathArgs", "opts", "docZip") 137) 138 139func init() { 140 android.RegisterModuleType("doc_defaults", DocDefaultsFactory) 141 android.RegisterModuleType("stubs_defaults", StubsDefaultsFactory) 142 143 android.RegisterModuleType("droiddoc", DroiddocFactory) 144 android.RegisterModuleType("droiddoc_host", DroiddocHostFactory) 145 android.RegisterModuleType("droiddoc_exported_dir", ExportedDroiddocDirFactory) 146 android.RegisterModuleType("javadoc", JavadocFactory) 147 android.RegisterModuleType("javadoc_host", JavadocHostFactory) 148 149 android.RegisterModuleType("droidstubs", DroidstubsFactory) 150 android.RegisterModuleType("droidstubs_host", DroidstubsHostFactory) 151} 152 153var ( 154 srcsLibTag = dependencyTag{name: "sources from javalib"} 155) 156 157type JavadocProperties struct { 158 // list of source files used to compile the Java module. May be .java, .logtags, .proto, 159 // or .aidl files. 160 Srcs []string `android:"path,arch_variant"` 161 162 // list of directories rooted at the Android.bp file that will 163 // be added to the search paths for finding source files when passing package names. 164 Local_sourcepaths []string 165 166 // list of source files that should not be used to build the Java module. 167 // This is most useful in the arch/multilib variants to remove non-common files 168 // filegroup or genrule can be included within this property. 169 Exclude_srcs []string `android:"path,arch_variant"` 170 171 // list of java libraries that will be in the classpath. 172 Libs []string `android:"arch_variant"` 173 174 // don't build against the default libraries (bootclasspath, ext, and framework for device 175 // targets) 176 No_standard_libs *bool 177 178 // don't build against the framework libraries (ext, and framework for device targets) 179 No_framework_libs *bool 180 181 // the java library (in classpath) for documentation that provides java srcs and srcjars. 182 Srcs_lib *string 183 184 // the base dirs under srcs_lib will be scanned for java srcs. 185 Srcs_lib_whitelist_dirs []string 186 187 // the sub dirs under srcs_lib_whitelist_dirs will be scanned for java srcs. 188 Srcs_lib_whitelist_pkgs []string 189 190 // If set to false, don't allow this module(-docs.zip) to be exported. Defaults to true. 191 Installable *bool 192 193 // if not blank, set to the version of the sdk to compile against 194 Sdk_version *string `android:"arch_variant"` 195 196 Aidl struct { 197 // Top level directories to pass to aidl tool 198 Include_dirs []string 199 200 // Directories rooted at the Android.bp file to pass to aidl tool 201 Local_include_dirs []string 202 } 203 204 // If not blank, set the java version passed to javadoc as -source 205 Java_version *string 206 207 // local files that are used within user customized droiddoc options. 208 Arg_files []string `android:"path"` 209 210 // user customized droiddoc args. 211 // Available variables for substitution: 212 // 213 // $(location <label>): the path to the arg_files with name <label> 214 Args *string 215 216 // names of the output files used in args that will be generated 217 Out []string 218} 219 220type ApiToCheck struct { 221 // path to the API txt file that the new API extracted from source code is checked 222 // against. The path can be local to the module or from other module (via :module syntax). 223 Api_file *string `android:"path"` 224 225 // path to the API txt file that the new @removed API extractd from source code is 226 // checked against. The path can be local to the module or from other module (via 227 // :module syntax). 228 Removed_api_file *string `android:"path"` 229 230 // Arguments to the apicheck tool. 231 Args *string 232} 233 234type DroiddocProperties struct { 235 // directory relative to top of the source tree that contains doc templates files. 236 Custom_template *string 237 238 // directories under current module source which contains html/jd files. 239 Html_dirs []string 240 241 // set a value in the Clearsilver hdf namespace. 242 Hdf []string 243 244 // proofread file contains all of the text content of the javadocs concatenated into one file, 245 // suitable for spell-checking and other goodness. 246 Proofread_file *string `android:"path"` 247 248 // a todo file lists the program elements that are missing documentation. 249 // At some point, this might be improved to show more warnings. 250 Todo_file *string `android:"path"` 251 252 // directory under current module source that provide additional resources (images). 253 Resourcesdir *string 254 255 // resources output directory under out/soong/.intermediates. 256 Resourcesoutdir *string 257 258 // if set to true, collect the values used by the Dev tools and 259 // write them in files packaged with the SDK. Defaults to false. 260 Write_sdk_values *bool 261 262 // index.html under current module will be copied to docs out dir, if not null. 263 Static_doc_index_redirect *string `android:"path"` 264 265 // source.properties under current module will be copied to docs out dir, if not null. 266 Static_doc_properties *string `android:"path"` 267 268 // a list of files under current module source dir which contains known tags in Java sources. 269 // filegroup or genrule can be included within this property. 270 Knowntags []string `android:"path"` 271 272 // the tag name used to distinguish if the API files belong to public/system/test. 273 Api_tag_name *string 274 275 // the generated public API filename by Doclava. 276 Api_filename *string 277 278 // the generated public Dex API filename by Doclava. 279 Dex_api_filename *string 280 281 // the generated private API filename by Doclava. 282 Private_api_filename *string 283 284 // the generated private Dex API filename by Doclava. 285 Private_dex_api_filename *string 286 287 // the generated removed API filename by Doclava. 288 Removed_api_filename *string 289 290 // the generated removed Dex API filename by Doclava. 291 Removed_dex_api_filename *string 292 293 // mapping of dex signatures to source file and line number. This is a temporary property and 294 // will be deleted; you probably shouldn't be using it. 295 Dex_mapping_filename *string 296 297 // the generated exact API filename by Doclava. 298 Exact_api_filename *string 299 300 // the generated proguard filename by Doclava. 301 Proguard_filename *string 302 303 // if set to false, don't allow droiddoc to generate stubs source files. Defaults to true. 304 Create_stubs *bool 305 306 Check_api struct { 307 Last_released ApiToCheck 308 309 Current ApiToCheck 310 311 // do not perform API check against Last_released, in the case that both two specified API 312 // files by Last_released are modules which don't exist. 313 Ignore_missing_latest_api *bool `blueprint:"mutated"` 314 } 315 316 // if set to true, generate docs through Dokka instead of Doclava. 317 Dokka_enabled *bool 318} 319 320type DroidstubsProperties struct { 321 // the tag name used to distinguish if the API files belong to public/system/test. 322 Api_tag_name *string 323 324 // the generated public API filename by Metalava. 325 Api_filename *string 326 327 // the generated public Dex API filename by Metalava. 328 Dex_api_filename *string 329 330 // the generated private API filename by Metalava. 331 Private_api_filename *string 332 333 // the generated private Dex API filename by Metalava. 334 Private_dex_api_filename *string 335 336 // the generated removed API filename by Metalava. 337 Removed_api_filename *string 338 339 // the generated removed Dex API filename by Metalava. 340 Removed_dex_api_filename *string 341 342 // mapping of dex signatures to source file and line number. This is a temporary property and 343 // will be deleted; you probably shouldn't be using it. 344 Dex_mapping_filename *string 345 346 // the generated exact API filename by Metalava. 347 Exact_api_filename *string 348 349 // the generated proguard filename by Metalava. 350 Proguard_filename *string 351 352 Check_api struct { 353 Last_released ApiToCheck 354 355 Current ApiToCheck 356 357 // do not perform API check against Last_released, in the case that both two specified API 358 // files by Last_released are modules which don't exist. 359 Ignore_missing_latest_api *bool `blueprint:"mutated"` 360 } 361 362 // user can specify the version of previous released API file in order to do compatibility check. 363 Previous_api *string `android:"path"` 364 365 // is set to true, Metalava will allow framework SDK to contain annotations. 366 Annotations_enabled *bool 367 368 // a list of top-level directories containing files to merge qualifier annotations (i.e. those intended to be included in the stubs written) from. 369 Merge_annotations_dirs []string 370 371 // a list of top-level directories containing Java stub files to merge show/hide annotations from. 372 Merge_inclusion_annotations_dirs []string 373 374 // a file containing a list of classes to do nullability validation for. 375 Validate_nullability_from_list *string 376 377 // a file containing expected warnings produced by validation of nullability annotations. 378 Check_nullability_warnings *string 379 380 // if set to true, allow Metalava to generate doc_stubs source files. Defaults to false. 381 Create_doc_stubs *bool 382 383 // is set to true, Metalava will allow framework SDK to contain API levels annotations. 384 Api_levels_annotations_enabled *bool 385 386 // the dirs which Metalava extracts API levels annotations from. 387 Api_levels_annotations_dirs []string 388 389 // if set to true, collect the values used by the Dev tools and 390 // write them in files packaged with the SDK. Defaults to false. 391 Write_sdk_values *bool 392 393 // If set to true, .xml based public API file will be also generated, and 394 // JDiff tool will be invoked to genreate javadoc files. Defaults to false. 395 Jdiff_enabled *bool 396} 397 398// 399// Common flags passed down to build rule 400// 401type droiddocBuilderFlags struct { 402 bootClasspathArgs string 403 classpathArgs string 404 sourcepathArgs string 405 dokkaClasspathArgs string 406 aidlFlags string 407 aidlDeps android.Paths 408 409 doclavaStubsFlags string 410 doclavaDocsFlags string 411 postDoclavaCmds string 412 413 metalavaStubsFlags string 414 metalavaAnnotationsFlags string 415 metalavaMergeAnnoDirFlags string 416 metalavaInclusionAnnotationsFlags string 417 metalavaApiLevelsAnnotationsFlags string 418 419 metalavaApiToXmlFlags string 420} 421 422func InitDroiddocModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) { 423 android.InitAndroidArchModule(module, hod, android.MultilibCommon) 424 android.InitDefaultableModule(module) 425} 426 427func apiCheckEnabled(apiToCheck ApiToCheck, apiVersionTag string) bool { 428 if String(apiToCheck.Api_file) != "" && String(apiToCheck.Removed_api_file) != "" { 429 return true 430 } else if String(apiToCheck.Api_file) != "" { 431 panic("for " + apiVersionTag + " removed_api_file has to be non-empty!") 432 } else if String(apiToCheck.Removed_api_file) != "" { 433 panic("for " + apiVersionTag + " api_file has to be non-empty!") 434 } 435 436 return false 437} 438 439func ignoreMissingModules(ctx android.BottomUpMutatorContext, apiToCheck *ApiToCheck) { 440 api_file := String(apiToCheck.Api_file) 441 removed_api_file := String(apiToCheck.Removed_api_file) 442 443 api_module := android.SrcIsModule(api_file) 444 removed_api_module := android.SrcIsModule(removed_api_file) 445 446 if api_module == "" || removed_api_module == "" { 447 return 448 } 449 450 if ctx.OtherModuleExists(api_module) || ctx.OtherModuleExists(removed_api_module) { 451 return 452 } 453 454 apiToCheck.Api_file = nil 455 apiToCheck.Removed_api_file = nil 456} 457 458type ApiFilePath interface { 459 ApiFilePath() android.Path 460} 461 462func transformUpdateApi(ctx android.ModuleContext, destApiFile, destRemovedApiFile, 463 srcApiFile, srcRemovedApiFile android.Path, output android.WritablePath) { 464 ctx.Build(pctx, android.BuildParams{ 465 Rule: updateApi, 466 Description: "Update API", 467 Output: output, 468 Implicits: append(android.Paths{}, srcApiFile, srcRemovedApiFile, 469 destApiFile, destRemovedApiFile), 470 Args: map[string]string{ 471 "destApiFile": destApiFile.String(), 472 "srcApiFile": srcApiFile.String(), 473 "destRemovedApiFile": destRemovedApiFile.String(), 474 "srcRemovedApiFile": srcRemovedApiFile.String(), 475 }, 476 }) 477} 478 479// 480// Javadoc 481// 482type Javadoc struct { 483 android.ModuleBase 484 android.DefaultableModuleBase 485 486 properties JavadocProperties 487 488 srcJars android.Paths 489 srcFiles android.Paths 490 sourcepaths android.Paths 491 argFiles android.Paths 492 493 args string 494 495 docZip android.WritablePath 496 stubsSrcJar android.WritablePath 497} 498 499func (j *Javadoc) Srcs() android.Paths { 500 return android.Paths{j.stubsSrcJar} 501} 502 503func JavadocFactory() android.Module { 504 module := &Javadoc{} 505 506 module.AddProperties(&module.properties) 507 508 InitDroiddocModule(module, android.HostAndDeviceSupported) 509 return module 510} 511 512func JavadocHostFactory() android.Module { 513 module := &Javadoc{} 514 515 module.AddProperties(&module.properties) 516 517 InitDroiddocModule(module, android.HostSupported) 518 return module 519} 520 521var _ android.SourceFileProducer = (*Javadoc)(nil) 522 523func (j *Javadoc) sdkVersion() string { 524 return String(j.properties.Sdk_version) 525} 526 527func (j *Javadoc) minSdkVersion() string { 528 return j.sdkVersion() 529} 530 531func (j *Javadoc) targetSdkVersion() string { 532 return j.sdkVersion() 533} 534 535func (j *Javadoc) addDeps(ctx android.BottomUpMutatorContext) { 536 if ctx.Device() { 537 if !Bool(j.properties.No_standard_libs) { 538 sdkDep := decodeSdkDep(ctx, sdkContext(j)) 539 if sdkDep.useDefaultLibs { 540 ctx.AddVariationDependencies(nil, bootClasspathTag, config.DefaultBootclasspathLibraries...) 541 if ctx.Config().TargetOpenJDK9() { 542 ctx.AddVariationDependencies(nil, systemModulesTag, config.DefaultSystemModules) 543 } 544 if !Bool(j.properties.No_framework_libs) { 545 ctx.AddVariationDependencies(nil, libTag, config.DefaultLibraries...) 546 } 547 } else if sdkDep.useModule { 548 if ctx.Config().TargetOpenJDK9() { 549 ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules) 550 } 551 ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.modules...) 552 } 553 } 554 } 555 556 ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...) 557 if j.properties.Srcs_lib != nil { 558 ctx.AddVariationDependencies(nil, srcsLibTag, *j.properties.Srcs_lib) 559 } 560} 561 562func (j *Javadoc) genWhitelistPathPrefixes(whitelistPathPrefixes map[string]bool) { 563 for _, dir := range j.properties.Srcs_lib_whitelist_dirs { 564 for _, pkg := range j.properties.Srcs_lib_whitelist_pkgs { 565 // convert foo.bar.baz to foo/bar/baz 566 pkgAsPath := filepath.Join(strings.Split(pkg, ".")...) 567 prefix := filepath.Join(dir, pkgAsPath) 568 if _, found := whitelistPathPrefixes[prefix]; !found { 569 whitelistPathPrefixes[prefix] = true 570 } 571 } 572 } 573} 574 575func (j *Javadoc) collectAidlFlags(ctx android.ModuleContext, deps deps) droiddocBuilderFlags { 576 var flags droiddocBuilderFlags 577 578 flags.aidlFlags, flags.aidlDeps = j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs) 579 580 return flags 581} 582 583func (j *Javadoc) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.OptionalPath, 584 aidlIncludeDirs android.Paths) (string, android.Paths) { 585 586 aidlIncludes := android.PathsForModuleSrc(ctx, j.properties.Aidl.Local_include_dirs) 587 aidlIncludes = append(aidlIncludes, android.PathsForSource(ctx, j.properties.Aidl.Include_dirs)...) 588 589 var flags []string 590 var deps android.Paths 591 592 if aidlPreprocess.Valid() { 593 flags = append(flags, "-p"+aidlPreprocess.String()) 594 deps = append(deps, aidlPreprocess.Path()) 595 } else { 596 flags = append(flags, android.JoinWithPrefix(aidlIncludeDirs.Strings(), "-I")) 597 } 598 599 flags = append(flags, android.JoinWithPrefix(aidlIncludes.Strings(), "-I")) 600 flags = append(flags, "-I"+android.PathForModuleSrc(ctx).String()) 601 if src := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "src"); src.Valid() { 602 flags = append(flags, "-I"+src.String()) 603 } 604 605 return strings.Join(flags, " "), deps 606} 607 608func (j *Javadoc) genSources(ctx android.ModuleContext, srcFiles android.Paths, 609 flags droiddocBuilderFlags) android.Paths { 610 611 outSrcFiles := make(android.Paths, 0, len(srcFiles)) 612 613 for _, srcFile := range srcFiles { 614 switch srcFile.Ext() { 615 case ".aidl": 616 javaFile := genAidl(ctx, srcFile, flags.aidlFlags, flags.aidlDeps) 617 outSrcFiles = append(outSrcFiles, javaFile) 618 case ".sysprop": 619 javaFile := genSysprop(ctx, srcFile) 620 outSrcFiles = append(outSrcFiles, javaFile) 621 default: 622 outSrcFiles = append(outSrcFiles, srcFile) 623 } 624 } 625 626 return outSrcFiles 627} 628 629func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps { 630 var deps deps 631 632 sdkDep := decodeSdkDep(ctx, sdkContext(j)) 633 if sdkDep.invalidVersion { 634 ctx.AddMissingDependencies(sdkDep.modules) 635 } else if sdkDep.useFiles { 636 deps.bootClasspath = append(deps.bootClasspath, sdkDep.jars...) 637 } 638 639 ctx.VisitDirectDeps(func(module android.Module) { 640 otherName := ctx.OtherModuleName(module) 641 tag := ctx.OtherModuleDependencyTag(module) 642 643 switch tag { 644 case bootClasspathTag: 645 if dep, ok := module.(Dependency); ok { 646 deps.bootClasspath = append(deps.bootClasspath, dep.ImplementationJars()...) 647 } else { 648 panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName())) 649 } 650 case libTag: 651 switch dep := module.(type) { 652 case SdkLibraryDependency: 653 deps.classpath = append(deps.classpath, dep.SdkImplementationJars(ctx, j.sdkVersion())...) 654 case Dependency: 655 deps.classpath = append(deps.classpath, dep.HeaderJars()...) 656 case android.SourceFileProducer: 657 checkProducesJars(ctx, dep) 658 deps.classpath = append(deps.classpath, dep.Srcs()...) 659 default: 660 ctx.ModuleErrorf("depends on non-java module %q", otherName) 661 } 662 case srcsLibTag: 663 switch dep := module.(type) { 664 case Dependency: 665 srcs := dep.(SrcDependency).CompiledSrcs() 666 whitelistPathPrefixes := make(map[string]bool) 667 j.genWhitelistPathPrefixes(whitelistPathPrefixes) 668 for _, src := range srcs { 669 if _, ok := src.(android.WritablePath); ok { // generated sources 670 deps.srcs = append(deps.srcs, src) 671 } else { // select source path for documentation based on whitelist path prefixs. 672 for k := range whitelistPathPrefixes { 673 if strings.HasPrefix(src.Rel(), k) { 674 deps.srcs = append(deps.srcs, src) 675 break 676 } 677 } 678 } 679 } 680 deps.srcJars = append(deps.srcJars, dep.(SrcDependency).CompiledSrcJars()...) 681 default: 682 ctx.ModuleErrorf("depends on non-java module %q", otherName) 683 } 684 case systemModulesTag: 685 if deps.systemModules != nil { 686 panic("Found two system module dependencies") 687 } 688 sm := module.(*SystemModules) 689 if sm.outputFile == nil { 690 panic("Missing directory for system module dependency") 691 } 692 deps.systemModules = sm.outputFile 693 } 694 }) 695 // do not pass exclude_srcs directly when expanding srcFiles since exclude_srcs 696 // may contain filegroup or genrule. 697 srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs) 698 flags := j.collectAidlFlags(ctx, deps) 699 srcFiles = j.genSources(ctx, srcFiles, flags) 700 701 // srcs may depend on some genrule output. 702 j.srcJars = srcFiles.FilterByExt(".srcjar") 703 j.srcJars = append(j.srcJars, deps.srcJars...) 704 705 j.srcFiles = srcFiles.FilterOutByExt(".srcjar") 706 j.srcFiles = append(j.srcFiles, deps.srcs...) 707 708 j.docZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"docs.zip") 709 j.stubsSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar") 710 711 if j.properties.Local_sourcepaths == nil && len(j.srcFiles) > 0 { 712 j.properties.Local_sourcepaths = append(j.properties.Local_sourcepaths, ".") 713 } 714 j.sourcepaths = android.PathsForModuleSrc(ctx, j.properties.Local_sourcepaths) 715 716 j.argFiles = android.PathsForModuleSrc(ctx, j.properties.Arg_files) 717 argFilesMap := map[string]string{} 718 argFileLabels := []string{} 719 720 for _, label := range j.properties.Arg_files { 721 var paths = android.PathsForModuleSrc(ctx, []string{label}) 722 if _, exists := argFilesMap[label]; !exists { 723 argFilesMap[label] = strings.Join(paths.Strings(), " ") 724 argFileLabels = append(argFileLabels, label) 725 } else { 726 ctx.ModuleErrorf("multiple arg_files for %q, %q and %q", 727 label, argFilesMap[label], paths) 728 } 729 } 730 731 var err error 732 j.args, err = android.Expand(String(j.properties.Args), func(name string) (string, error) { 733 if strings.HasPrefix(name, "location ") { 734 label := strings.TrimSpace(strings.TrimPrefix(name, "location ")) 735 if paths, ok := argFilesMap[label]; ok { 736 return paths, nil 737 } else { 738 return "", fmt.Errorf("unknown location label %q, expecting one of %q", 739 label, strings.Join(argFileLabels, ", ")) 740 } 741 } else if name == "genDir" { 742 return android.PathForModuleGen(ctx).String(), nil 743 } 744 return "", fmt.Errorf("unknown variable '$(%s)'", name) 745 }) 746 747 if err != nil { 748 ctx.PropertyErrorf("args", "%s", err.Error()) 749 } 750 751 return deps 752} 753 754func (j *Javadoc) DepsMutator(ctx android.BottomUpMutatorContext) { 755 j.addDeps(ctx) 756} 757 758func (j *Javadoc) GenerateAndroidBuildActions(ctx android.ModuleContext) { 759 deps := j.collectDeps(ctx) 760 761 var implicits android.Paths 762 implicits = append(implicits, deps.bootClasspath...) 763 implicits = append(implicits, deps.classpath...) 764 765 var bootClasspathArgs, classpathArgs, sourcepathArgs string 766 767 javaVersion := getJavaVersion(ctx, String(j.properties.Java_version), sdkContext(j)) 768 if len(deps.bootClasspath) > 0 { 769 var systemModules classpath 770 if deps.systemModules != nil { 771 systemModules = append(systemModules, deps.systemModules) 772 } 773 bootClasspathArgs = systemModules.FormJavaSystemModulesPath("--system ", ctx.Device()) 774 bootClasspathArgs = bootClasspathArgs + " --patch-module java.base=." 775 } 776 if len(deps.classpath.Strings()) > 0 { 777 classpathArgs = "-classpath " + strings.Join(deps.classpath.Strings(), ":") 778 } 779 780 implicits = append(implicits, j.srcJars...) 781 implicits = append(implicits, j.argFiles...) 782 783 opts := "-source " + javaVersion + " -J-Xmx1024m -XDignore.symbol.file -Xdoclint:none" 784 785 sourcepathArgs = "-sourcepath " + strings.Join(j.sourcepaths.Strings(), ":") 786 787 ctx.Build(pctx, android.BuildParams{ 788 Rule: javadoc, 789 Description: "Javadoc", 790 Output: j.stubsSrcJar, 791 ImplicitOutput: j.docZip, 792 Inputs: j.srcFiles, 793 Implicits: implicits, 794 Args: map[string]string{ 795 "outDir": android.PathForModuleOut(ctx, "out").String(), 796 "srcJarDir": android.PathForModuleOut(ctx, "srcjars").String(), 797 "stubsDir": android.PathForModuleOut(ctx, "stubsDir").String(), 798 "srcJars": strings.Join(j.srcJars.Strings(), " "), 799 "opts": opts, 800 "bootclasspathArgs": bootClasspathArgs, 801 "classpathArgs": classpathArgs, 802 "sourcepathArgs": sourcepathArgs, 803 "docZip": j.docZip.String(), 804 }, 805 }) 806} 807 808// 809// Droiddoc 810// 811type Droiddoc struct { 812 Javadoc 813 814 properties DroiddocProperties 815 apiFile android.WritablePath 816 dexApiFile android.WritablePath 817 privateApiFile android.WritablePath 818 privateDexApiFile android.WritablePath 819 removedApiFile android.WritablePath 820 removedDexApiFile android.WritablePath 821 exactApiFile android.WritablePath 822 apiMappingFile android.WritablePath 823 proguardFile android.WritablePath 824 825 checkCurrentApiTimestamp android.WritablePath 826 updateCurrentApiTimestamp android.WritablePath 827 checkLastReleasedApiTimestamp android.WritablePath 828 829 apiFilePath android.Path 830} 831 832func DroiddocFactory() android.Module { 833 module := &Droiddoc{} 834 835 module.AddProperties(&module.properties, 836 &module.Javadoc.properties) 837 838 InitDroiddocModule(module, android.HostAndDeviceSupported) 839 return module 840} 841 842func DroiddocHostFactory() android.Module { 843 module := &Droiddoc{} 844 845 module.AddProperties(&module.properties, 846 &module.Javadoc.properties) 847 848 InitDroiddocModule(module, android.HostSupported) 849 return module 850} 851 852func (d *Droiddoc) ApiFilePath() android.Path { 853 return d.apiFilePath 854} 855 856func (d *Droiddoc) DepsMutator(ctx android.BottomUpMutatorContext) { 857 d.Javadoc.addDeps(ctx) 858 859 if Bool(d.properties.Check_api.Ignore_missing_latest_api) { 860 ignoreMissingModules(ctx, &d.properties.Check_api.Last_released) 861 } 862 863 if String(d.properties.Custom_template) != "" { 864 ctx.AddDependency(ctx.Module(), droiddocTemplateTag, String(d.properties.Custom_template)) 865 } 866} 867 868func (d *Droiddoc) initBuilderFlags(ctx android.ModuleContext, implicits *android.Paths, 869 deps deps) (droiddocBuilderFlags, error) { 870 var flags droiddocBuilderFlags 871 872 *implicits = append(*implicits, deps.bootClasspath...) 873 *implicits = append(*implicits, deps.classpath...) 874 875 if len(deps.bootClasspath.Strings()) > 0 { 876 // For OpenJDK 8 we can use -bootclasspath to define the core libraries code. 877 flags.bootClasspathArgs = deps.bootClasspath.FormJavaClassPath("-bootclasspath") 878 } 879 flags.classpathArgs = deps.classpath.FormJavaClassPath("-classpath") 880 // Dokka doesn't support bootClasspath, so combine these two classpath vars for Dokka. 881 dokkaClasspath := classpath{} 882 dokkaClasspath = append(dokkaClasspath, deps.bootClasspath...) 883 dokkaClasspath = append(dokkaClasspath, deps.classpath...) 884 flags.dokkaClasspathArgs = dokkaClasspath.FormJavaClassPath("-classpath") 885 886 // TODO(nanzhang): Remove this if- statement once we finish migration for all Doclava 887 // based stubs generation. 888 // In the future, all the docs generation depends on Metalava stubs (droidstubs) srcjar 889 // dir. We need add the srcjar dir to -sourcepath arg, so that Javadoc can figure out 890 // the correct package name base path. 891 if len(d.Javadoc.properties.Local_sourcepaths) > 0 { 892 flags.sourcepathArgs = "-sourcepath " + strings.Join(d.Javadoc.sourcepaths.Strings(), ":") 893 } else { 894 flags.sourcepathArgs = "-sourcepath " + android.PathForModuleOut(ctx, "srcjars").String() 895 } 896 897 return flags, nil 898} 899 900func (d *Droiddoc) collectDoclavaDocsFlags(ctx android.ModuleContext, implicits *android.Paths, 901 jsilver, doclava android.Path) string { 902 903 *implicits = append(*implicits, jsilver) 904 *implicits = append(*implicits, doclava) 905 906 var date string 907 if runtime.GOOS == "darwin" { 908 date = `date -r` 909 } else { 910 date = `date -d` 911 } 912 913 // Droiddoc always gets "-source 1.8" because it doesn't support 1.9 sources. For modules with 1.9 914 // sources, droiddoc will get sources produced by metalava which will have already stripped out the 915 // 1.9 language features. 916 args := " -source 1.8 -J-Xmx1600m -J-XX:-OmitStackTraceInFastThrow -XDignore.symbol.file " + 917 "-doclet com.google.doclava.Doclava -docletpath " + jsilver.String() + ":" + doclava.String() + " " + 918 "-hdf page.build " + ctx.Config().BuildId() + "-" + ctx.Config().BuildNumberFromFile() + " " + 919 `-hdf page.now "$$(` + date + ` @$$(cat ` + ctx.Config().Getenv("BUILD_DATETIME_FILE") + `) "+%d %b %Y %k:%M")" ` 920 921 if String(d.properties.Custom_template) == "" { 922 // TODO: This is almost always droiddoc-templates-sdk 923 ctx.PropertyErrorf("custom_template", "must specify a template") 924 } 925 926 ctx.VisitDirectDepsWithTag(droiddocTemplateTag, func(m android.Module) { 927 if t, ok := m.(*ExportedDroiddocDir); ok { 928 *implicits = append(*implicits, t.deps...) 929 args = args + " -templatedir " + t.dir.String() 930 } else { 931 ctx.PropertyErrorf("custom_template", "module %q is not a droiddoc_template", ctx.OtherModuleName(m)) 932 } 933 }) 934 935 if len(d.properties.Html_dirs) > 0 { 936 htmlDir := d.properties.Html_dirs[0] 937 *implicits = append(*implicits, android.PathsForModuleSrc(ctx, []string{filepath.Join(d.properties.Html_dirs[0], "**/*")})...) 938 args = args + " -htmldir " + htmlDir 939 } 940 941 if len(d.properties.Html_dirs) > 1 { 942 htmlDir2 := d.properties.Html_dirs[1] 943 *implicits = append(*implicits, android.PathsForModuleSrc(ctx, []string{filepath.Join(htmlDir2, "**/*")})...) 944 args = args + " -htmldir2 " + htmlDir2 945 } 946 947 if len(d.properties.Html_dirs) > 2 { 948 ctx.PropertyErrorf("html_dirs", "Droiddoc only supports up to 2 html dirs") 949 } 950 951 knownTags := android.PathsForModuleSrc(ctx, d.properties.Knowntags) 952 *implicits = append(*implicits, knownTags...) 953 954 for _, kt := range knownTags { 955 args = args + " -knowntags " + kt.String() 956 } 957 958 for _, hdf := range d.properties.Hdf { 959 args = args + " -hdf " + hdf 960 } 961 962 if String(d.properties.Proofread_file) != "" { 963 proofreadFile := android.PathForModuleOut(ctx, String(d.properties.Proofread_file)) 964 args = args + " -proofread " + proofreadFile.String() 965 } 966 967 if String(d.properties.Todo_file) != "" { 968 // tricky part: 969 // we should not compute full path for todo_file through PathForModuleOut(). 970 // the non-standard doclet will get the full path relative to "-o". 971 args = args + " -todo " + String(d.properties.Todo_file) 972 } 973 974 if String(d.properties.Resourcesdir) != "" { 975 // TODO: should we add files under resourcesDir to the implicits? It seems that 976 // resourcesDir is one sub dir of htmlDir 977 resourcesDir := android.PathForModuleSrc(ctx, String(d.properties.Resourcesdir)) 978 args = args + " -resourcesdir " + resourcesDir.String() 979 } 980 981 if String(d.properties.Resourcesoutdir) != "" { 982 // TODO: it seems -resourceoutdir reference/android/images/ didn't get generated anywhere. 983 args = args + " -resourcesoutdir " + String(d.properties.Resourcesoutdir) 984 } 985 return args 986} 987 988func (d *Droiddoc) collectStubsFlags(ctx android.ModuleContext, 989 implicitOutputs *android.WritablePaths) string { 990 var doclavaFlags string 991 if apiCheckEnabled(d.properties.Check_api.Current, "current") || 992 apiCheckEnabled(d.properties.Check_api.Last_released, "last_released") || 993 String(d.properties.Api_filename) != "" { 994 d.apiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_api.txt") 995 doclavaFlags += " -api " + d.apiFile.String() 996 *implicitOutputs = append(*implicitOutputs, d.apiFile) 997 d.apiFilePath = d.apiFile 998 } 999 1000 if apiCheckEnabled(d.properties.Check_api.Current, "current") || 1001 apiCheckEnabled(d.properties.Check_api.Last_released, "last_released") || 1002 String(d.properties.Removed_api_filename) != "" { 1003 d.removedApiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_removed.txt") 1004 doclavaFlags += " -removedApi " + d.removedApiFile.String() 1005 *implicitOutputs = append(*implicitOutputs, d.removedApiFile) 1006 } 1007 1008 if String(d.properties.Private_api_filename) != "" { 1009 d.privateApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_api_filename)) 1010 doclavaFlags += " -privateApi " + d.privateApiFile.String() 1011 *implicitOutputs = append(*implicitOutputs, d.privateApiFile) 1012 } 1013 1014 if String(d.properties.Dex_api_filename) != "" { 1015 d.dexApiFile = android.PathForModuleOut(ctx, String(d.properties.Dex_api_filename)) 1016 doclavaFlags += " -dexApi " + d.dexApiFile.String() 1017 *implicitOutputs = append(*implicitOutputs, d.dexApiFile) 1018 } 1019 1020 if String(d.properties.Private_dex_api_filename) != "" { 1021 d.privateDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_dex_api_filename)) 1022 doclavaFlags += " -privateDexApi " + d.privateDexApiFile.String() 1023 *implicitOutputs = append(*implicitOutputs, d.privateDexApiFile) 1024 } 1025 1026 if String(d.properties.Removed_dex_api_filename) != "" { 1027 d.removedDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Removed_dex_api_filename)) 1028 doclavaFlags += " -removedDexApi " + d.removedDexApiFile.String() 1029 *implicitOutputs = append(*implicitOutputs, d.removedDexApiFile) 1030 } 1031 1032 if String(d.properties.Exact_api_filename) != "" { 1033 d.exactApiFile = android.PathForModuleOut(ctx, String(d.properties.Exact_api_filename)) 1034 doclavaFlags += " -exactApi " + d.exactApiFile.String() 1035 *implicitOutputs = append(*implicitOutputs, d.exactApiFile) 1036 } 1037 1038 if String(d.properties.Dex_mapping_filename) != "" { 1039 d.apiMappingFile = android.PathForModuleOut(ctx, String(d.properties.Dex_mapping_filename)) 1040 doclavaFlags += " -apiMapping " + d.apiMappingFile.String() 1041 *implicitOutputs = append(*implicitOutputs, d.apiMappingFile) 1042 } 1043 1044 if String(d.properties.Proguard_filename) != "" { 1045 d.proguardFile = android.PathForModuleOut(ctx, String(d.properties.Proguard_filename)) 1046 doclavaFlags += " -proguard " + d.proguardFile.String() 1047 *implicitOutputs = append(*implicitOutputs, d.proguardFile) 1048 } 1049 1050 if BoolDefault(d.properties.Create_stubs, true) { 1051 doclavaFlags += " -stubs " + android.PathForModuleOut(ctx, "stubsDir").String() 1052 } 1053 1054 if Bool(d.properties.Write_sdk_values) { 1055 doclavaFlags += " -sdkvalues " + android.PathForModuleOut(ctx, "out").String() 1056 } 1057 1058 return doclavaFlags 1059} 1060 1061func (d *Droiddoc) getPostDoclavaCmds(ctx android.ModuleContext, implicits *android.Paths) string { 1062 var cmds string 1063 if String(d.properties.Static_doc_index_redirect) != "" { 1064 static_doc_index_redirect := ctx.ExpandSource(String(d.properties.Static_doc_index_redirect), 1065 "static_doc_index_redirect") 1066 *implicits = append(*implicits, static_doc_index_redirect) 1067 cmds = cmds + " && cp " + static_doc_index_redirect.String() + " " + 1068 android.PathForModuleOut(ctx, "out", "index.html").String() 1069 } 1070 1071 if String(d.properties.Static_doc_properties) != "" { 1072 static_doc_properties := ctx.ExpandSource(String(d.properties.Static_doc_properties), 1073 "static_doc_properties") 1074 *implicits = append(*implicits, static_doc_properties) 1075 cmds = cmds + " && cp " + static_doc_properties.String() + " " + 1076 android.PathForModuleOut(ctx, "out", "source.properties").String() 1077 } 1078 return cmds 1079} 1080 1081func (d *Droiddoc) transformDoclava(ctx android.ModuleContext, implicits android.Paths, 1082 implicitOutputs android.WritablePaths, 1083 bootclasspathArgs, classpathArgs, sourcepathArgs, opts, postDoclavaCmds string) { 1084 ctx.Build(pctx, android.BuildParams{ 1085 Rule: javadoc, 1086 Description: "Doclava", 1087 Output: d.Javadoc.stubsSrcJar, 1088 Inputs: d.Javadoc.srcFiles, 1089 Implicits: implicits, 1090 ImplicitOutputs: implicitOutputs, 1091 Args: map[string]string{ 1092 "outDir": android.PathForModuleOut(ctx, "out").String(), 1093 "srcJarDir": android.PathForModuleOut(ctx, "srcjars").String(), 1094 "stubsDir": android.PathForModuleOut(ctx, "stubsDir").String(), 1095 "srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "), 1096 "opts": opts, 1097 "bootclasspathArgs": bootclasspathArgs, 1098 "classpathArgs": classpathArgs, 1099 "sourcepathArgs": sourcepathArgs, 1100 "docZip": d.Javadoc.docZip.String(), 1101 "postDoclavaCmds": postDoclavaCmds, 1102 }, 1103 }) 1104} 1105 1106func (d *Droiddoc) transformCheckApi(ctx android.ModuleContext, apiFile, removedApiFile android.Path, 1107 checkApiClasspath classpath, msg, opts string, output android.WritablePath) { 1108 ctx.Build(pctx, android.BuildParams{ 1109 Rule: apiCheck, 1110 Description: "Doclava Check API", 1111 Output: output, 1112 Inputs: nil, 1113 Implicits: append(android.Paths{apiFile, removedApiFile, d.apiFile, d.removedApiFile}, 1114 checkApiClasspath...), 1115 Args: map[string]string{ 1116 "msg": msg, 1117 "classpath": checkApiClasspath.FormJavaClassPath(""), 1118 "opts": opts, 1119 "apiFile": apiFile.String(), 1120 "apiFileToCheck": d.apiFile.String(), 1121 "removedApiFile": removedApiFile.String(), 1122 "removedApiFileToCheck": d.removedApiFile.String(), 1123 }, 1124 }) 1125} 1126 1127func (d *Droiddoc) transformDokka(ctx android.ModuleContext, implicits android.Paths, 1128 classpathArgs, opts string) { 1129 ctx.Build(pctx, android.BuildParams{ 1130 Rule: dokka, 1131 Description: "Dokka", 1132 Output: d.Javadoc.stubsSrcJar, 1133 Inputs: d.Javadoc.srcFiles, 1134 Implicits: implicits, 1135 Args: map[string]string{ 1136 "outDir": android.PathForModuleOut(ctx, "dokka-out").String(), 1137 "srcJarDir": android.PathForModuleOut(ctx, "dokka-srcjars").String(), 1138 "stubsDir": android.PathForModuleOut(ctx, "dokka-stubsDir").String(), 1139 "srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "), 1140 "classpathArgs": classpathArgs, 1141 "opts": opts, 1142 "docZip": d.Javadoc.docZip.String(), 1143 }, 1144 }) 1145} 1146 1147func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) { 1148 deps := d.Javadoc.collectDeps(ctx) 1149 1150 jsilver := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "jsilver.jar") 1151 doclava := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "doclava.jar") 1152 java8Home := ctx.Config().Getenv("ANDROID_JAVA8_HOME") 1153 checkApiClasspath := classpath{jsilver, doclava, android.PathForSource(ctx, java8Home, "lib/tools.jar")} 1154 1155 var implicits android.Paths 1156 implicits = append(implicits, d.Javadoc.srcJars...) 1157 implicits = append(implicits, d.Javadoc.argFiles...) 1158 1159 var implicitOutputs android.WritablePaths 1160 implicitOutputs = append(implicitOutputs, d.Javadoc.docZip) 1161 for _, o := range d.Javadoc.properties.Out { 1162 implicitOutputs = append(implicitOutputs, android.PathForModuleGen(ctx, o)) 1163 } 1164 1165 flags, err := d.initBuilderFlags(ctx, &implicits, deps) 1166 if err != nil { 1167 return 1168 } 1169 1170 flags.doclavaStubsFlags = d.collectStubsFlags(ctx, &implicitOutputs) 1171 if Bool(d.properties.Dokka_enabled) { 1172 d.transformDokka(ctx, implicits, flags.classpathArgs, d.Javadoc.args) 1173 } else { 1174 flags.doclavaDocsFlags = d.collectDoclavaDocsFlags(ctx, &implicits, jsilver, doclava) 1175 flags.postDoclavaCmds = d.getPostDoclavaCmds(ctx, &implicits) 1176 d.transformDoclava(ctx, implicits, implicitOutputs, flags.bootClasspathArgs, flags.classpathArgs, 1177 flags.sourcepathArgs, flags.doclavaDocsFlags+flags.doclavaStubsFlags+" "+d.Javadoc.args, 1178 flags.postDoclavaCmds) 1179 } 1180 1181 if apiCheckEnabled(d.properties.Check_api.Current, "current") && 1182 !ctx.Config().IsPdkBuild() { 1183 apiFile := ctx.ExpandSource(String(d.properties.Check_api.Current.Api_file), 1184 "check_api.current.api_file") 1185 removedApiFile := ctx.ExpandSource(String(d.properties.Check_api.Current.Removed_api_file), 1186 "check_api.current_removed_api_file") 1187 1188 d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, "check_current_api.timestamp") 1189 d.transformCheckApi(ctx, apiFile, removedApiFile, checkApiClasspath, 1190 fmt.Sprintf(`\n******************************\n`+ 1191 `You have tried to change the API from what has been previously approved.\n\n`+ 1192 `To make these errors go away, you have two choices:\n`+ 1193 ` 1. You can add '@hide' javadoc comments to the methods, etc. listed in the\n`+ 1194 ` errors above.\n\n`+ 1195 ` 2. You can update current.txt by executing the following command:\n`+ 1196 ` make %s-update-current-api\n\n`+ 1197 ` To submit the revised current.txt to the main Android repository,\n`+ 1198 ` you will need approval.\n`+ 1199 `******************************\n`, ctx.ModuleName()), String(d.properties.Check_api.Current.Args), 1200 d.checkCurrentApiTimestamp) 1201 1202 d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, "update_current_api.timestamp") 1203 transformUpdateApi(ctx, apiFile, removedApiFile, d.apiFile, d.removedApiFile, 1204 d.updateCurrentApiTimestamp) 1205 } 1206 1207 if apiCheckEnabled(d.properties.Check_api.Last_released, "last_released") && 1208 !ctx.Config().IsPdkBuild() { 1209 apiFile := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Api_file), 1210 "check_api.last_released.api_file") 1211 removedApiFile := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Removed_api_file), 1212 "check_api.last_released.removed_api_file") 1213 1214 d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, "check_last_released_api.timestamp") 1215 d.transformCheckApi(ctx, apiFile, removedApiFile, checkApiClasspath, 1216 `\n******************************\n`+ 1217 `You have tried to change the API from what has been previously released in\n`+ 1218 `an SDK. Please fix the errors listed above.\n`+ 1219 `******************************\n`, String(d.properties.Check_api.Last_released.Args), 1220 d.checkLastReleasedApiTimestamp) 1221 } 1222} 1223 1224// 1225// Droidstubs 1226// 1227type Droidstubs struct { 1228 Javadoc 1229 1230 properties DroidstubsProperties 1231 apiFile android.WritablePath 1232 apiXmlFile android.WritablePath 1233 lastReleasedApiXmlFile android.WritablePath 1234 dexApiFile android.WritablePath 1235 privateApiFile android.WritablePath 1236 privateDexApiFile android.WritablePath 1237 removedApiFile android.WritablePath 1238 removedDexApiFile android.WritablePath 1239 apiMappingFile android.WritablePath 1240 exactApiFile android.WritablePath 1241 proguardFile android.WritablePath 1242 nullabilityWarningsFile android.WritablePath 1243 1244 checkCurrentApiTimestamp android.WritablePath 1245 updateCurrentApiTimestamp android.WritablePath 1246 checkLastReleasedApiTimestamp android.WritablePath 1247 1248 checkNullabilityWarningsTimestamp android.WritablePath 1249 1250 annotationsZip android.WritablePath 1251 apiVersionsXml android.WritablePath 1252 1253 apiFilePath android.Path 1254 1255 jdiffDocZip android.WritablePath 1256 jdiffStubsSrcJar android.WritablePath 1257} 1258 1259func DroidstubsFactory() android.Module { 1260 module := &Droidstubs{} 1261 1262 module.AddProperties(&module.properties, 1263 &module.Javadoc.properties) 1264 1265 InitDroiddocModule(module, android.HostAndDeviceSupported) 1266 return module 1267} 1268 1269func DroidstubsHostFactory() android.Module { 1270 module := &Droidstubs{} 1271 1272 module.AddProperties(&module.properties, 1273 &module.Javadoc.properties) 1274 1275 InitDroiddocModule(module, android.HostSupported) 1276 return module 1277} 1278 1279func (d *Droidstubs) ApiFilePath() android.Path { 1280 return d.apiFilePath 1281} 1282 1283func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) { 1284 d.Javadoc.addDeps(ctx) 1285 1286 if Bool(d.properties.Check_api.Ignore_missing_latest_api) { 1287 ignoreMissingModules(ctx, &d.properties.Check_api.Last_released) 1288 } 1289 1290 if len(d.properties.Merge_annotations_dirs) != 0 { 1291 for _, mergeAnnotationsDir := range d.properties.Merge_annotations_dirs { 1292 ctx.AddDependency(ctx.Module(), metalavaMergeAnnotationsDirTag, mergeAnnotationsDir) 1293 } 1294 } 1295 1296 if len(d.properties.Merge_inclusion_annotations_dirs) != 0 { 1297 for _, mergeInclusionAnnotationsDir := range d.properties.Merge_inclusion_annotations_dirs { 1298 ctx.AddDependency(ctx.Module(), metalavaMergeInclusionAnnotationsDirTag, mergeInclusionAnnotationsDir) 1299 } 1300 } 1301 1302 if len(d.properties.Api_levels_annotations_dirs) != 0 { 1303 for _, apiLevelsAnnotationsDir := range d.properties.Api_levels_annotations_dirs { 1304 ctx.AddDependency(ctx.Module(), metalavaAPILevelsAnnotationsDirTag, apiLevelsAnnotationsDir) 1305 } 1306 } 1307} 1308 1309func (d *Droidstubs) initBuilderFlags(ctx android.ModuleContext, implicits *android.Paths, 1310 deps deps) (droiddocBuilderFlags, error) { 1311 var flags droiddocBuilderFlags 1312 1313 *implicits = append(*implicits, deps.bootClasspath...) 1314 *implicits = append(*implicits, deps.classpath...) 1315 1316 // continue to use -bootclasspath even if Metalava under -source 1.9 is enabled 1317 // since it doesn't support system modules yet. 1318 if len(deps.bootClasspath.Strings()) > 0 { 1319 // For OpenJDK 8 we can use -bootclasspath to define the core libraries code. 1320 flags.bootClasspathArgs = deps.bootClasspath.FormJavaClassPath("-bootclasspath") 1321 } 1322 flags.classpathArgs = deps.classpath.FormJavaClassPath("-classpath") 1323 1324 flags.sourcepathArgs = "-sourcepath \"" + strings.Join(d.Javadoc.sourcepaths.Strings(), ":") + "\"" 1325 return flags, nil 1326} 1327 1328func (d *Droidstubs) collectStubsFlags(ctx android.ModuleContext, 1329 implicitOutputs *android.WritablePaths) string { 1330 var metalavaFlags string 1331 if apiCheckEnabled(d.properties.Check_api.Current, "current") || 1332 apiCheckEnabled(d.properties.Check_api.Last_released, "last_released") || 1333 String(d.properties.Api_filename) != "" { 1334 d.apiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_api.txt") 1335 metalavaFlags = metalavaFlags + " --api " + d.apiFile.String() 1336 *implicitOutputs = append(*implicitOutputs, d.apiFile) 1337 d.apiFilePath = d.apiFile 1338 } 1339 1340 if apiCheckEnabled(d.properties.Check_api.Current, "current") || 1341 apiCheckEnabled(d.properties.Check_api.Last_released, "last_released") || 1342 String(d.properties.Removed_api_filename) != "" { 1343 d.removedApiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_removed.txt") 1344 metalavaFlags = metalavaFlags + " --removed-api " + d.removedApiFile.String() 1345 *implicitOutputs = append(*implicitOutputs, d.removedApiFile) 1346 } 1347 1348 if String(d.properties.Private_api_filename) != "" { 1349 d.privateApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_api_filename)) 1350 metalavaFlags = metalavaFlags + " --private-api " + d.privateApiFile.String() 1351 *implicitOutputs = append(*implicitOutputs, d.privateApiFile) 1352 } 1353 1354 if String(d.properties.Dex_api_filename) != "" { 1355 d.dexApiFile = android.PathForModuleOut(ctx, String(d.properties.Dex_api_filename)) 1356 metalavaFlags += " --dex-api " + d.dexApiFile.String() 1357 *implicitOutputs = append(*implicitOutputs, d.dexApiFile) 1358 } 1359 1360 if String(d.properties.Private_dex_api_filename) != "" { 1361 d.privateDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_dex_api_filename)) 1362 metalavaFlags = metalavaFlags + " --private-dex-api " + d.privateDexApiFile.String() 1363 *implicitOutputs = append(*implicitOutputs, d.privateDexApiFile) 1364 } 1365 1366 if String(d.properties.Removed_dex_api_filename) != "" { 1367 d.removedDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Removed_dex_api_filename)) 1368 metalavaFlags = metalavaFlags + " --removed-dex-api " + d.removedDexApiFile.String() 1369 *implicitOutputs = append(*implicitOutputs, d.removedDexApiFile) 1370 } 1371 1372 if String(d.properties.Exact_api_filename) != "" { 1373 d.exactApiFile = android.PathForModuleOut(ctx, String(d.properties.Exact_api_filename)) 1374 metalavaFlags = metalavaFlags + " --exact-api " + d.exactApiFile.String() 1375 *implicitOutputs = append(*implicitOutputs, d.exactApiFile) 1376 } 1377 1378 if String(d.properties.Dex_mapping_filename) != "" { 1379 d.apiMappingFile = android.PathForModuleOut(ctx, String(d.properties.Dex_mapping_filename)) 1380 metalavaFlags = metalavaFlags + " --dex-api-mapping " + d.apiMappingFile.String() 1381 *implicitOutputs = append(*implicitOutputs, d.apiMappingFile) 1382 } 1383 1384 if String(d.properties.Proguard_filename) != "" { 1385 d.proguardFile = android.PathForModuleOut(ctx, String(d.properties.Proguard_filename)) 1386 metalavaFlags += " --proguard " + d.proguardFile.String() 1387 *implicitOutputs = append(*implicitOutputs, d.proguardFile) 1388 } 1389 1390 if Bool(d.properties.Write_sdk_values) { 1391 metalavaFlags = metalavaFlags + " --sdk-values " + android.PathForModuleOut(ctx, "out").String() 1392 } 1393 1394 if Bool(d.properties.Create_doc_stubs) { 1395 metalavaFlags += " --doc-stubs " + android.PathForModuleOut(ctx, "stubsDir").String() 1396 } else { 1397 metalavaFlags += " --stubs " + android.PathForModuleOut(ctx, "stubsDir").String() 1398 } 1399 return metalavaFlags 1400} 1401 1402func (d *Droidstubs) collectAnnotationsFlags(ctx android.ModuleContext, 1403 implicits *android.Paths, implicitOutputs *android.WritablePaths) (string, string) { 1404 var flags, mergeAnnoDirFlags string 1405 if Bool(d.properties.Annotations_enabled) { 1406 flags += " --include-annotations" 1407 validatingNullability := 1408 strings.Contains(d.Javadoc.args, "--validate-nullability-from-merged-stubs") || 1409 String(d.properties.Validate_nullability_from_list) != "" 1410 migratingNullability := String(d.properties.Previous_api) != "" 1411 if !(migratingNullability || validatingNullability) { 1412 ctx.PropertyErrorf("previous_api", 1413 "has to be non-empty if annotations was enabled (unless validating nullability)") 1414 } 1415 if migratingNullability { 1416 previousApi := android.PathForModuleSrc(ctx, String(d.properties.Previous_api)) 1417 *implicits = append(*implicits, previousApi) 1418 flags += " --migrate-nullness " + previousApi.String() 1419 } 1420 if s := String(d.properties.Validate_nullability_from_list); s != "" { 1421 flags += " --validate-nullability-from-list " + android.PathForModuleSrc(ctx, s).String() 1422 } 1423 if validatingNullability { 1424 d.nullabilityWarningsFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_nullability_warnings.txt") 1425 *implicitOutputs = append(*implicitOutputs, d.nullabilityWarningsFile) 1426 flags += " --nullability-warnings-txt " + d.nullabilityWarningsFile.String() 1427 } 1428 1429 d.annotationsZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"_annotations.zip") 1430 *implicitOutputs = append(*implicitOutputs, d.annotationsZip) 1431 1432 flags += " --extract-annotations " + d.annotationsZip.String() 1433 1434 if len(d.properties.Merge_annotations_dirs) == 0 { 1435 ctx.PropertyErrorf("merge_annotations_dirs", 1436 "has to be non-empty if annotations was enabled!") 1437 } 1438 ctx.VisitDirectDepsWithTag(metalavaMergeAnnotationsDirTag, func(m android.Module) { 1439 if t, ok := m.(*ExportedDroiddocDir); ok { 1440 *implicits = append(*implicits, t.deps...) 1441 mergeAnnoDirFlags += " --merge-qualifier-annotations " + t.dir.String() 1442 } else { 1443 ctx.PropertyErrorf("merge_annotations_dirs", 1444 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m)) 1445 } 1446 }) 1447 flags += mergeAnnoDirFlags 1448 // TODO(tnorbye): find owners to fix these warnings when annotation was enabled. 1449 flags += " --hide HiddenTypedefConstant --hide SuperfluousPrefix --hide AnnotationExtraction" 1450 } 1451 1452 return flags, mergeAnnoDirFlags 1453} 1454 1455func (d *Droidstubs) collectInclusionAnnotationsFlags(ctx android.ModuleContext, 1456 implicits *android.Paths, implicitOutputs *android.WritablePaths) string { 1457 var flags string 1458 ctx.VisitDirectDepsWithTag(metalavaMergeInclusionAnnotationsDirTag, func(m android.Module) { 1459 if t, ok := m.(*ExportedDroiddocDir); ok { 1460 *implicits = append(*implicits, t.deps...) 1461 flags += " --merge-inclusion-annotations " + t.dir.String() 1462 } else { 1463 ctx.PropertyErrorf("merge_inclusion_annotations_dirs", 1464 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m)) 1465 } 1466 }) 1467 1468 return flags 1469} 1470 1471func (d *Droidstubs) collectAPILevelsAnnotationsFlags(ctx android.ModuleContext, 1472 implicits *android.Paths, implicitOutputs *android.WritablePaths) string { 1473 var flags string 1474 if Bool(d.properties.Api_levels_annotations_enabled) { 1475 d.apiVersionsXml = android.PathForModuleOut(ctx, "api-versions.xml") 1476 *implicitOutputs = append(*implicitOutputs, d.apiVersionsXml) 1477 1478 if len(d.properties.Api_levels_annotations_dirs) == 0 { 1479 ctx.PropertyErrorf("api_levels_annotations_dirs", 1480 "has to be non-empty if api levels annotations was enabled!") 1481 } 1482 1483 flags = " --generate-api-levels " + d.apiVersionsXml.String() + " --apply-api-levels " + 1484 d.apiVersionsXml.String() + " --current-version " + ctx.Config().PlatformSdkVersion() + 1485 " --current-codename " + ctx.Config().PlatformSdkCodename() + " " 1486 1487 ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) { 1488 if t, ok := m.(*ExportedDroiddocDir); ok { 1489 var androidJars android.Paths 1490 for _, dep := range t.deps { 1491 if strings.HasSuffix(dep.String(), "android.jar") { 1492 androidJars = append(androidJars, dep) 1493 } 1494 } 1495 *implicits = append(*implicits, androidJars...) 1496 flags += " --android-jar-pattern " + t.dir.String() + "/%/public/android.jar " 1497 } else { 1498 ctx.PropertyErrorf("api_levels_annotations_dirs", 1499 "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m)) 1500 } 1501 }) 1502 1503 } 1504 1505 return flags 1506} 1507 1508func (d *Droidstubs) collectApiToXmlFlags(ctx android.ModuleContext, implicits *android.Paths, 1509 implicitOutputs *android.WritablePaths) string { 1510 var flags string 1511 if Bool(d.properties.Jdiff_enabled) && !ctx.Config().IsPdkBuild() { 1512 if d.apiFile.String() == "" { 1513 ctx.ModuleErrorf("API signature file has to be specified in Metalava when jdiff is enabled.") 1514 } 1515 1516 d.apiXmlFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_api.xml") 1517 *implicitOutputs = append(*implicitOutputs, d.apiXmlFile) 1518 1519 flags = " --api-xml " + d.apiXmlFile.String() 1520 1521 if String(d.properties.Check_api.Last_released.Api_file) == "" { 1522 ctx.PropertyErrorf("check_api.last_released.api_file", 1523 "has to be non-empty if jdiff was enabled!") 1524 } 1525 lastReleasedApi := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Api_file), 1526 "check_api.last_released.api_file") 1527 *implicits = append(*implicits, lastReleasedApi) 1528 1529 d.lastReleasedApiXmlFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_last_released_api.xml") 1530 *implicitOutputs = append(*implicitOutputs, d.lastReleasedApiXmlFile) 1531 1532 flags += " --convert-to-jdiff " + lastReleasedApi.String() + " " + 1533 d.lastReleasedApiXmlFile.String() 1534 } 1535 1536 return flags 1537} 1538 1539func (d *Droidstubs) transformMetalava(ctx android.ModuleContext, implicits android.Paths, 1540 implicitOutputs android.WritablePaths, javaVersion, 1541 bootclasspathArgs, classpathArgs, sourcepathArgs, opts string) { 1542 1543 ctx.Build(pctx, android.BuildParams{ 1544 Rule: metalava, 1545 Description: "Metalava", 1546 Output: d.Javadoc.stubsSrcJar, 1547 Inputs: d.Javadoc.srcFiles, 1548 Implicits: implicits, 1549 ImplicitOutputs: implicitOutputs, 1550 Args: map[string]string{ 1551 "outDir": android.PathForModuleOut(ctx, "out").String(), 1552 "srcJarDir": android.PathForModuleOut(ctx, "srcjars").String(), 1553 "stubsDir": android.PathForModuleOut(ctx, "stubsDir").String(), 1554 "srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "), 1555 "javaVersion": javaVersion, 1556 "bootclasspathArgs": bootclasspathArgs, 1557 "classpathArgs": classpathArgs, 1558 "sourcepathArgs": sourcepathArgs, 1559 "opts": opts, 1560 }, 1561 }) 1562} 1563 1564func (d *Droidstubs) transformCheckApi(ctx android.ModuleContext, 1565 apiFile, removedApiFile android.Path, implicits android.Paths, 1566 javaVersion, bootclasspathArgs, classpathArgs, sourcepathArgs, opts, subdir, msg string, 1567 output android.WritablePath) { 1568 ctx.Build(pctx, android.BuildParams{ 1569 Rule: metalavaApiCheck, 1570 Description: "Metalava Check API", 1571 Output: output, 1572 Inputs: d.Javadoc.srcFiles, 1573 Implicits: append(android.Paths{apiFile, removedApiFile, d.apiFile, d.removedApiFile}, 1574 implicits...), 1575 Args: map[string]string{ 1576 "srcJarDir": android.PathForModuleOut(ctx, subdir, "srcjars").String(), 1577 "srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "), 1578 "javaVersion": javaVersion, 1579 "bootclasspathArgs": bootclasspathArgs, 1580 "classpathArgs": classpathArgs, 1581 "sourcepathArgs": sourcepathArgs, 1582 "opts": opts, 1583 "msg": msg, 1584 }, 1585 }) 1586} 1587 1588func (d *Droidstubs) transformJdiff(ctx android.ModuleContext, implicits android.Paths, 1589 implicitOutputs android.WritablePaths, 1590 bootclasspathArgs, classpathArgs, sourcepathArgs, opts string) { 1591 ctx.Build(pctx, android.BuildParams{ 1592 Rule: javadoc, 1593 Description: "Jdiff", 1594 Output: d.jdiffStubsSrcJar, 1595 Inputs: d.Javadoc.srcFiles, 1596 Implicits: implicits, 1597 ImplicitOutputs: implicitOutputs, 1598 Args: map[string]string{ 1599 "outDir": android.PathForModuleOut(ctx, "jdiff-out").String(), 1600 "srcJarDir": android.PathForModuleOut(ctx, "jdiff-srcjars").String(), 1601 "stubsDir": android.PathForModuleOut(ctx, "jdiff-stubsDir").String(), 1602 "srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "), 1603 "opts": opts, 1604 "bootclasspathArgs": bootclasspathArgs, 1605 "classpathArgs": classpathArgs, 1606 "sourcepathArgs": sourcepathArgs, 1607 "docZip": d.jdiffDocZip.String(), 1608 }, 1609 }) 1610} 1611 1612func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) { 1613 deps := d.Javadoc.collectDeps(ctx) 1614 1615 javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), sdkContext(d)) 1616 1617 var implicits android.Paths 1618 implicits = append(implicits, d.Javadoc.srcJars...) 1619 implicits = append(implicits, d.Javadoc.argFiles...) 1620 1621 var implicitOutputs android.WritablePaths 1622 for _, o := range d.Javadoc.properties.Out { 1623 implicitOutputs = append(implicitOutputs, android.PathForModuleGen(ctx, o)) 1624 } 1625 1626 flags, err := d.initBuilderFlags(ctx, &implicits, deps) 1627 metalavaCheckApiImplicits := implicits 1628 jdiffImplicits := implicits 1629 1630 if err != nil { 1631 return 1632 } 1633 1634 flags.metalavaStubsFlags = d.collectStubsFlags(ctx, &implicitOutputs) 1635 flags.metalavaAnnotationsFlags, flags.metalavaMergeAnnoDirFlags = 1636 d.collectAnnotationsFlags(ctx, &implicits, &implicitOutputs) 1637 flags.metalavaInclusionAnnotationsFlags = d.collectInclusionAnnotationsFlags(ctx, &implicits, &implicitOutputs) 1638 flags.metalavaApiLevelsAnnotationsFlags = d.collectAPILevelsAnnotationsFlags(ctx, &implicits, &implicitOutputs) 1639 flags.metalavaApiToXmlFlags = d.collectApiToXmlFlags(ctx, &implicits, &implicitOutputs) 1640 1641 if strings.Contains(d.Javadoc.args, "--generate-documentation") { 1642 // Currently Metalava have the ability to invoke Javadoc in a seperate process. 1643 // Pass "-nodocs" to suppress the Javadoc invocation when Metalava receives 1644 // "--generate-documentation" arg. This is not needed when Metalava removes this feature. 1645 d.Javadoc.args = d.Javadoc.args + " -nodocs " 1646 } 1647 d.transformMetalava(ctx, implicits, implicitOutputs, javaVersion, 1648 flags.bootClasspathArgs, flags.classpathArgs, flags.sourcepathArgs, 1649 flags.metalavaStubsFlags+flags.metalavaAnnotationsFlags+flags.metalavaInclusionAnnotationsFlags+ 1650 flags.metalavaApiLevelsAnnotationsFlags+flags.metalavaApiToXmlFlags+" "+d.Javadoc.args) 1651 1652 if apiCheckEnabled(d.properties.Check_api.Current, "current") && 1653 !ctx.Config().IsPdkBuild() { 1654 apiFile := ctx.ExpandSource(String(d.properties.Check_api.Current.Api_file), 1655 "check_api.current.api_file") 1656 removedApiFile := ctx.ExpandSource(String(d.properties.Check_api.Current.Removed_api_file), 1657 "check_api.current_removed_api_file") 1658 1659 d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, "check_current_api.timestamp") 1660 opts := " " + d.Javadoc.args + " --check-compatibility:api:current " + apiFile.String() + 1661 " --check-compatibility:removed:current " + removedApiFile.String() + 1662 flags.metalavaInclusionAnnotationsFlags + flags.metalavaMergeAnnoDirFlags + " " 1663 1664 d.transformCheckApi(ctx, apiFile, removedApiFile, metalavaCheckApiImplicits, 1665 javaVersion, flags.bootClasspathArgs, flags.classpathArgs, flags.sourcepathArgs, opts, "current-apicheck", 1666 fmt.Sprintf(`\n******************************\n`+ 1667 `You have tried to change the API from what has been previously approved.\n\n`+ 1668 `To make these errors go away, you have two choices:\n`+ 1669 ` 1. You can add '@hide' javadoc comments to the methods, etc. listed in the\n`+ 1670 ` errors above.\n\n`+ 1671 ` 2. You can update current.txt by executing the following command:\n`+ 1672 ` make %s-update-current-api\n\n`+ 1673 ` To submit the revised current.txt to the main Android repository,\n`+ 1674 ` you will need approval.\n`+ 1675 `******************************\n`, ctx.ModuleName()), 1676 d.checkCurrentApiTimestamp) 1677 1678 d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, "update_current_api.timestamp") 1679 transformUpdateApi(ctx, apiFile, removedApiFile, d.apiFile, d.removedApiFile, 1680 d.updateCurrentApiTimestamp) 1681 } 1682 1683 if apiCheckEnabled(d.properties.Check_api.Last_released, "last_released") && 1684 !ctx.Config().IsPdkBuild() { 1685 apiFile := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Api_file), 1686 "check_api.last_released.api_file") 1687 removedApiFile := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Removed_api_file), 1688 "check_api.last_released.removed_api_file") 1689 1690 d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, "check_last_released_api.timestamp") 1691 opts := " " + d.Javadoc.args + " --check-compatibility:api:released " + apiFile.String() + 1692 flags.metalavaInclusionAnnotationsFlags + " --check-compatibility:removed:released " + 1693 removedApiFile.String() + flags.metalavaMergeAnnoDirFlags + " " 1694 1695 d.transformCheckApi(ctx, apiFile, removedApiFile, metalavaCheckApiImplicits, 1696 javaVersion, flags.bootClasspathArgs, flags.classpathArgs, flags.sourcepathArgs, opts, "last-apicheck", 1697 `\n******************************\n`+ 1698 `You have tried to change the API from what has been previously released in\n`+ 1699 `an SDK. Please fix the errors listed above.\n`+ 1700 `******************************\n`, 1701 d.checkLastReleasedApiTimestamp) 1702 } 1703 1704 if String(d.properties.Check_nullability_warnings) != "" { 1705 if d.nullabilityWarningsFile == nil { 1706 ctx.PropertyErrorf("check_nullability_warnings", 1707 "Cannot specify check_nullability_warnings unless validating nullability") 1708 } 1709 checkNullabilityWarnings := ctx.ExpandSource(String(d.properties.Check_nullability_warnings), 1710 "check_nullability_warnings") 1711 d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, "check_nullability_warnings.timestamp") 1712 msg := fmt.Sprintf(`\n******************************\n`+ 1713 `The warnings encountered during nullability annotation validation did\n`+ 1714 `not match the checked in file of expected warnings. The diffs are shown\n`+ 1715 `above. You have two options:\n`+ 1716 ` 1. Resolve the differences by editing the nullability annotations.\n`+ 1717 ` 2. Update the file of expected warnings by running:\n`+ 1718 ` cp %s %s\n`+ 1719 ` and submitting the updated file as part of your change.`, 1720 d.nullabilityWarningsFile, checkNullabilityWarnings) 1721 ctx.Build(pctx, android.BuildParams{ 1722 Rule: nullabilityWarningsCheck, 1723 Description: "Nullability Warnings Check", 1724 Output: d.checkNullabilityWarningsTimestamp, 1725 Implicits: android.Paths{checkNullabilityWarnings, d.nullabilityWarningsFile}, 1726 Args: map[string]string{ 1727 "expected": checkNullabilityWarnings.String(), 1728 "actual": d.nullabilityWarningsFile.String(), 1729 "msg": msg, 1730 }, 1731 }) 1732 } 1733 1734 if Bool(d.properties.Jdiff_enabled) && !ctx.Config().IsPdkBuild() { 1735 1736 // Please sync with android-api-council@ before making any changes for the name of jdiffDocZip below 1737 // since there's cron job downstream that fetch this .zip file periodically. 1738 // See b/116221385 for reference. 1739 d.jdiffDocZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"jdiff-docs.zip") 1740 d.jdiffStubsSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"jdiff-stubs.srcjar") 1741 1742 var jdiffImplicitOutputs android.WritablePaths 1743 jdiffImplicitOutputs = append(jdiffImplicitOutputs, d.jdiffDocZip) 1744 1745 jdiff := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "jdiff.jar") 1746 jdiffImplicits = append(jdiffImplicits, android.Paths{jdiff, d.apiXmlFile, d.lastReleasedApiXmlFile}...) 1747 1748 opts := " -encoding UTF-8 -source 1.8 -J-Xmx1600m -XDignore.symbol.file " + 1749 "-doclet jdiff.JDiff -docletpath " + jdiff.String() + " -quiet " + 1750 "-newapi " + strings.TrimSuffix(d.apiXmlFile.Base(), d.apiXmlFile.Ext()) + 1751 " -newapidir " + filepath.Dir(d.apiXmlFile.String()) + 1752 " -oldapi " + strings.TrimSuffix(d.lastReleasedApiXmlFile.Base(), d.lastReleasedApiXmlFile.Ext()) + 1753 " -oldapidir " + filepath.Dir(d.lastReleasedApiXmlFile.String()) 1754 1755 d.transformJdiff(ctx, jdiffImplicits, jdiffImplicitOutputs, flags.bootClasspathArgs, flags.classpathArgs, 1756 flags.sourcepathArgs, opts) 1757 } 1758} 1759 1760// 1761// Exported Droiddoc Directory 1762// 1763var droiddocTemplateTag = dependencyTag{name: "droiddoc-template"} 1764var metalavaMergeAnnotationsDirTag = dependencyTag{name: "metalava-merge-annotations-dir"} 1765var metalavaMergeInclusionAnnotationsDirTag = dependencyTag{name: "metalava-merge-inclusion-annotations-dir"} 1766var metalavaAPILevelsAnnotationsDirTag = dependencyTag{name: "metalava-api-levels-annotations-dir"} 1767 1768type ExportedDroiddocDirProperties struct { 1769 // path to the directory containing Droiddoc related files. 1770 Path *string 1771} 1772 1773type ExportedDroiddocDir struct { 1774 android.ModuleBase 1775 1776 properties ExportedDroiddocDirProperties 1777 1778 deps android.Paths 1779 dir android.Path 1780} 1781 1782func ExportedDroiddocDirFactory() android.Module { 1783 module := &ExportedDroiddocDir{} 1784 module.AddProperties(&module.properties) 1785 android.InitAndroidModule(module) 1786 return module 1787} 1788 1789func (d *ExportedDroiddocDir) DepsMutator(android.BottomUpMutatorContext) {} 1790 1791func (d *ExportedDroiddocDir) GenerateAndroidBuildActions(ctx android.ModuleContext) { 1792 path := String(d.properties.Path) 1793 d.dir = android.PathForModuleSrc(ctx, path) 1794 d.deps = android.PathsForModuleSrc(ctx, []string{filepath.Join(path, "**/*")}) 1795} 1796 1797// 1798// Defaults 1799// 1800type DocDefaults struct { 1801 android.ModuleBase 1802 android.DefaultsModuleBase 1803} 1804 1805func (*DocDefaults) GenerateAndroidBuildActions(ctx android.ModuleContext) { 1806} 1807 1808func DocDefaultsFactory() android.Module { 1809 module := &DocDefaults{} 1810 1811 module.AddProperties( 1812 &JavadocProperties{}, 1813 &DroiddocProperties{}, 1814 ) 1815 1816 android.InitDefaultsModule(module) 1817 1818 return module 1819} 1820 1821func StubsDefaultsFactory() android.Module { 1822 module := &DocDefaults{} 1823 1824 module.AddProperties( 1825 &JavadocProperties{}, 1826 &DroidstubsProperties{}, 1827 ) 1828 1829 android.InitDefaultsModule(module) 1830 1831 return module 1832} 1833