gradle.configure (21636B)
1 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- 2 # vim: set filetype=python: 3 # This Source Code Form is subject to the terms of the Mozilla Public 4 # License, v. 2.0. If a copy of the MPL was not distributed with this 5 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 7 # If --with-gradle is specified, build mobile/android with Gradle. If no 8 # Gradle binary is specified use the in tree Gradle wrapper. The wrapper 9 # downloads and installs Gradle, which is good for local developers but not 10 # good in automation. 11 option( 12 "--without-gradle", 13 nargs="?", 14 help="Disable building mobile/android with Gradle " 15 "(argument: location of binary or wrapper (gradle/gradlew))", 16 ) 17 18 19 @depends("--with-gradle") 20 def with_gradle(value): 21 if not value: 22 die( 23 "Building --without-gradle is no longer supported: " 24 "see https://bugzilla.mozilla.org/show_bug.cgi?id=1414415." 25 ) 26 27 if value: 28 return True 29 30 31 @depends(host, "--with-gradle", build_environment) 32 @imports(_from="os.path", _import="isfile") 33 def gradle(host, value, build_env): 34 if len(value): 35 gradle = value[0] 36 else: 37 gradle = os.path.join(build_env.topsrcdir, "gradlew") 38 if host.os == "WINNT": 39 gradle = gradle + ".bat" 40 41 # TODO: verify that $GRADLE is executable. 42 if not isfile(gradle): 43 die("GRADLE must be executable: %s", gradle) 44 45 return gradle 46 47 48 set_config("GRADLE", gradle) 49 50 51 @dependable 52 @imports(_from="itertools", _import="chain") 53 def gradle_android_build_config(): 54 def capitalize(s): 55 # str.capitalize lower cases trailing letters. 56 if s: 57 return s[0].upper() + s[1:] 58 else: 59 return s 60 61 def variant(buildType): 62 return namespace( 63 buildType=buildType, 64 # Like 'Debug' 65 name="".join(capitalize(t) for t in chain((buildType,))), 66 ) 67 68 return namespace( 69 geckoview=namespace( 70 variant=variant("debug"), 71 ), 72 geckoview_example=namespace( 73 variant=variant("debug"), 74 ), 75 fenix=namespace( 76 variant=variant("debug"), 77 ), 78 focus=namespace( 79 variant=variant("debug"), 80 ), 81 ) 82 83 84 @depends(gradle_android_build_config) 85 def gradle_android_intermediates_folder(build_config): 86 """Path to intermediates classes folder.""" 87 88 def uncapitalize(s): 89 if s: 90 return s[0].lower() + s[1:] 91 else: 92 return s 93 94 def capitalize(s): 95 # str.capitalize lower cases trailing letters. 96 if s: 97 return s[0].upper() + s[1:] 98 else: 99 return s 100 101 buildType = uncapitalize(build_config.geckoview.variant.buildType) 102 103 return "gradle/build/mobile/android/geckoview/intermediates/javac/{}".format( 104 buildType, 105 ) 106 107 108 set_config( 109 "GRADLE_ANDROID_GECKOVIEW_APILINT_FOLDER", gradle_android_intermediates_folder 110 ) 111 112 113 @depends(gradle_android_build_config) 114 def gradle_android_geckoview_test_runner_bundle(build_config): 115 """Path to intermediates classes folder.""" 116 117 def uncapitalize(s): 118 if s: 119 return s[0].lower() + s[1:] 120 else: 121 return s 122 123 def capitalize(s): 124 # str.capitalize lower cases trailing letters. 125 if s: 126 return s[0].upper() + s[1:] 127 else: 128 return s 129 130 buildType = uncapitalize(build_config.geckoview.variant.buildType) 131 variant = uncapitalize(build_config.geckoview.variant.name) 132 133 return "gradle/build/mobile/android/test_runner/outputs/bundle/{}/test_runner-{}.aab".format( 134 variant, 135 buildType, 136 ) 137 138 139 set_config( 140 "GRADLE_ANDROID_GECKOVIEW_TEST_RUNNER_BUNDLE", 141 gradle_android_geckoview_test_runner_bundle, 142 ) 143 144 145 @depends(gradle_android_build_config) 146 def gradle_android_geckoview_example_bundle(build_config): 147 """Path to intermediates classes folder.""" 148 149 def uncapitalize(s): 150 if s: 151 return s[0].lower() + s[1:] 152 else: 153 return s 154 155 def capitalize(s): 156 # str.capitalize lower cases trailing letters. 157 if s: 158 return s[0].upper() + s[1:] 159 else: 160 return s 161 162 buildType = uncapitalize(build_config.geckoview.variant.buildType) 163 variant = uncapitalize(build_config.geckoview.variant.name) 164 165 return "gradle/build/mobile/android/geckoview_example/outputs/bundle/{}/geckoview_example-{}.aab".format( 166 variant, 167 buildType, 168 ) 169 170 171 set_config( 172 "GRADLE_ANDROID_GECKOVIEW_EXAMPLE_BUNDLE", gradle_android_geckoview_example_bundle 173 ) 174 175 176 @depends(gradle_android_build_config) 177 def gradle_android_variant_name(build_config): 178 """Like "Debug".""" 179 180 def uncapitalize(s): 181 if s: 182 return s[0].lower() + s[1:] 183 else: 184 return s 185 186 return namespace( 187 geckoview=uncapitalize(build_config.geckoview.variant.name), 188 ) 189 190 191 set_config( 192 "GRADLE_ANDROID_GECKOVIEW_VARIANT_NAME", gradle_android_variant_name.geckoview 193 ) 194 195 196 @dependable 197 def gradle_android_generate_sdk_bindings_tasks(): 198 """Gradle tasks run by |mach android generate-sdk-bindings|.""" 199 return [ 200 "geckoview:generateSDKBindings", 201 ] 202 203 204 set_config( 205 "GRADLE_ANDROID_GENERATE_SDK_BINDINGS_TASKS", 206 gradle_android_generate_sdk_bindings_tasks, 207 ) 208 209 210 @depends(gradle_android_build_config) 211 def gradle_android_generate_generated_jni_wrappers_tasks(build_config): 212 """Gradle tasks run by |mach android generate-generated-jni-wrappers|.""" 213 return [ 214 "geckoview:generateJNIWrappersForGenerated{geckoview.variant.name}".format( 215 geckoview=build_config.geckoview 216 ), 217 ] 218 219 220 set_config( 221 "GRADLE_ANDROID_GENERATE_GENERATED_JNI_WRAPPERS_TASKS", 222 gradle_android_generate_generated_jni_wrappers_tasks, 223 ) 224 225 226 @depends(gradle_android_build_config) 227 def gradle_android_test_tasks(build_config): 228 """Gradle tasks run by |mach android test|.""" 229 return [ 230 "geckoview:test{geckoview.variant.name}UnitTest".format( 231 geckoview=build_config.geckoview 232 ), 233 ] 234 235 236 set_config("GRADLE_ANDROID_TEST_TASKS", gradle_android_test_tasks) 237 238 239 @depends(gradle_android_build_config) 240 def gradle_android_lint_tasks(build_config): 241 """Gradle tasks run by |mach android lint|.""" 242 return [ 243 "geckoview:lint{geckoview.variant.name}".format( 244 geckoview=build_config.geckoview 245 ), 246 ] 247 248 249 set_config("GRADLE_ANDROID_LINT_TASKS", gradle_android_lint_tasks) 250 251 252 @depends(gradle_android_build_config) 253 def gradle_android_api_lint_tasks(build_config): 254 """Gradle tasks run by |mach android api-lint|.""" 255 # --no-configuration-cache will be removed in bug 1950099 256 return [ 257 "geckoview:apiLint{geckoview.variant.name}".format( 258 geckoview=build_config.geckoview 259 ), 260 "--no-configuration-cache", 261 ] 262 263 264 set_config("GRADLE_ANDROID_API_LINT_TASKS", gradle_android_api_lint_tasks) 265 266 267 def spotless_projects(): 268 return [ 269 "geckoview", 270 "geckoview_example", 271 "annotations", 272 "exoplayer2", 273 "messaging_example", 274 "port_messaging_example", 275 "test_runner", 276 ] 277 278 279 @dependable 280 def gradle_android_format_lint_apply_tasks(): 281 tasks = [] 282 for project in spotless_projects(): 283 for spotless_task in ["spotlessJavaApply", "spotlessKotlinApply"]: 284 tasks.append( 285 "{project}:{spotless_task}".format( 286 project=project, 287 spotless_task=spotless_task, 288 ) 289 ) 290 return tasks 291 292 293 set_config( 294 "GRADLE_ANDROID_FORMAT_LINT_FIX_TASKS", gradle_android_format_lint_apply_tasks 295 ) 296 297 298 @dependable 299 def gradle_android_format_lint_check_tasks(): 300 tasks = [] 301 for project in spotless_projects(): 302 for spotless_task in ["spotlessJavaCheck", "spotlessKotlinCheck"]: 303 tasks.append( 304 "{project}:{spotless_task}".format( 305 project=project, 306 spotless_task=spotless_task, 307 ) 308 ) 309 return tasks 310 311 312 set_config( 313 "GRADLE_ANDROID_FORMAT_LINT_CHECK_TASKS", gradle_android_format_lint_check_tasks 314 ) 315 316 set_config( 317 "GRADLE_ANDROID_FORMAT_LINT_FOLDERS", 318 [ 319 "mobile/android/annotations", 320 "mobile/android/geckoview", 321 "mobile/android/geckoview_example", 322 "mobile/android/test_runner", 323 "mobile/android/examples/messaging_example", 324 "mobile/android/examples/port_messaging_example", 325 ], 326 ) 327 328 329 @depends(gradle_android_build_config) 330 def gradle_android_checkstyle_tasks(build_config): 331 """Gradle tasks run by |mach android checkstyle|.""" 332 return [ 333 "geckoview:checkstyle{geckoview.variant.name}".format( 334 geckoview=build_config.geckoview 335 ), 336 ] 337 338 339 set_config("GRADLE_ANDROID_CHECKSTYLE_TASKS", gradle_android_checkstyle_tasks) 340 341 342 @depends(gradle_android_build_config) 343 def gradle_android_checkstyle_output_files(build_config): 344 def uncapitalize(s): 345 if s: 346 return s[0].lower() + s[1:] 347 else: 348 return s 349 350 variant = uncapitalize(build_config.geckoview.variant.name) 351 352 """Output folder for checkstyle""" 353 return [ 354 "gradle/build/mobile/android/geckoview/reports/checkstyle/{}.xml".format( 355 variant 356 ), 357 ] 358 359 360 set_config( 361 "GRADLE_ANDROID_CHECKSTYLE_OUTPUT_FILES", gradle_android_checkstyle_output_files 362 ) 363 364 365 option( 366 "--disable-android-bundle", 367 help="{Enable|Disable} AAB build", 368 ) 369 370 imply_option("--disable-android-bundle", False, when="--enable-address-sanitizer") 371 372 373 @depends(gradle_android_build_config) 374 def gradle_android_archive_geckoview_tasks(build_config): 375 """Gradle tasks run by |mach android archive-geckoview|.""" 376 tasks = [ 377 "geckoview:assemble{geckoview.variant.name}".format( 378 geckoview=build_config.geckoview 379 ), 380 "geckoview:assemble{geckoview.variant.name}AndroidTest".format( 381 geckoview=build_config.geckoview 382 ), 383 "messaging_example:assemble{geckoview_example.variant.name}".format( 384 geckoview_example=build_config.geckoview_example 385 ), 386 "port_messaging_example:assemble{geckoview_example.variant.name}".format( 387 geckoview_example=build_config.geckoview_example 388 ), 389 "geckoview:publish{geckoview.variant.name}PublicationToMavenRepository".format( 390 geckoview=build_config.geckoview 391 ), 392 "exoplayer2:publishDebugPublicationToMavenRepository", 393 ] 394 return tasks 395 396 397 set_config( 398 "GRADLE_ANDROID_ARCHIVE_GECKOVIEW_TASKS", gradle_android_archive_geckoview_tasks 399 ) 400 401 402 @depends(gradle_android_build_config, "--disable-android-bundle") 403 def gradle_android_archive_geckoview_subproject_tasks(build_config, aab_enabled): 404 """Gradle tasks run by |mach android archive-geckoview| if just building geckoview.""" 405 tasks = [ 406 "test_runner:assemble{geckoview_example.variant.name}".format( 407 geckoview_example=build_config.geckoview_example 408 ), 409 "geckoview_example:assemble{geckoview_example.variant.name}".format( 410 geckoview_example=build_config.geckoview_example 411 ), 412 ] 413 414 if aab_enabled: 415 tasks += [ 416 "test_runner:bundle{geckoview_example.variant.name}".format( 417 geckoview_example=build_config.geckoview_example 418 ), 419 "geckoview_example:bundle{geckoview_example.variant.name}".format( 420 geckoview_example=build_config.geckoview_example 421 ), 422 ] 423 return tasks 424 425 426 set_config( 427 "GRADLE_ANDROID_ARCHIVE_GECKOVIEW_SUBPROJECT_TASKS", 428 gradle_android_archive_geckoview_subproject_tasks, 429 ) 430 431 432 @depends(gradle_android_build_config, "--disable-android-bundle") 433 def gradle_android_archive_fenix_subproject_tasks(build_config, aab_enabled): 434 """Gradle tasks run by |mach android archive-geckoview| if just building fenix.""" 435 tasks = [ 436 "fenix:assemble{fenix.variant.name}".format(fenix=build_config.fenix), 437 ] 438 439 if aab_enabled: 440 tasks += [ 441 "fenix:bundle{fenix.variant.name}".format(fenix=build_config.fenix), 442 ] 443 return tasks 444 445 446 set_config( 447 "GRADLE_ANDROID_ARCHIVE_FENIX_SUBPROJECT_TASKS", 448 gradle_android_archive_fenix_subproject_tasks, 449 ) 450 451 452 @depends(gradle_android_build_config, "--disable-android-bundle") 453 def gradle_android_archive_focus_subproject_tasks(build_config, aab_enabled): 454 """Gradle tasks run by |mach android archive-geckoview| if just building focus.""" 455 tasks = [ 456 "focus-android:assemble{focus.variant.name}".format(focus=build_config.focus), 457 ] 458 if aab_enabled: 459 tasks += [ 460 "focus-android:bundle{focus.variant.name}".format(focus=build_config.focus), 461 ] 462 return tasks 463 464 465 set_config( 466 "GRADLE_ANDROID_ARCHIVE_FOCUS_SUBPROJECT_TASKS", 467 gradle_android_archive_focus_subproject_tasks, 468 ) 469 470 471 @depends(gradle_android_build_config) 472 def gradle_android_geckoview_docs_tasks(build_config): 473 """Gradle tasks run by |mach android geckoview-docs|.""" 474 return [ 475 "geckoview:javadoc{geckoview.variant.name}".format( 476 geckoview=build_config.geckoview 477 ), 478 ] 479 480 481 set_config("GRADLE_ANDROID_GECKOVIEW_DOCS_TASKS", gradle_android_geckoview_docs_tasks) 482 483 484 @depends(gradle_android_build_config) 485 def gradle_android_geckoview_docs_archive_tasks(build_config): 486 """Gradle tasks run by |mach android geckoview-docs --archive| or |... --upload.""" 487 return [ 488 "geckoview:javadocCopyJar{geckoview.variant.name}".format( 489 geckoview=build_config.geckoview 490 ), 491 ] 492 493 494 set_config( 495 "GRADLE_ANDROID_GECKOVIEW_DOCS_ARCHIVE_TASKS", 496 gradle_android_geckoview_docs_archive_tasks, 497 ) 498 499 500 @depends(gradle_android_build_config) 501 def gradle_android_geckoview_docs_output_files(build_config): 502 """Output files for GeckoView javadoc.""" 503 504 def uncapitalize(s): 505 if s: 506 return s[0].lower() + s[1:] 507 else: 508 return s 509 510 variant = uncapitalize(build_config.geckoview.variant.name) 511 512 return [ 513 "gradle/build/mobile/android/geckoview/reports/javadoc-results-{}.json".format( 514 variant 515 ), 516 ] 517 518 519 set_config( 520 "GRADLE_ANDROID_GECKOVIEW_DOCS_OUTPUT_FILES", 521 gradle_android_geckoview_docs_output_files, 522 ) 523 524 525 @depends(gradle_android_build_config) 526 def gradle_android_archive_coverage_artifacts_tasks(build_config): 527 """Gradle tasks run by |mach android archive-coverage-artifacts|.""" 528 return [ 529 "geckoview:archiveClassfiles{geckoview.variant.name}".format( 530 geckoview=build_config.geckoview 531 ), 532 "geckoview:copyCoverageDependencies", 533 ] 534 535 536 set_config( 537 "GRADLE_ANDROID_ARCHIVE_COVERAGE_ARTIFACTS_TASKS", 538 gradle_android_archive_coverage_artifacts_tasks, 539 ) 540 541 542 @depends(gradle_android_build_config) 543 def gradle_android_build_geckoview_example_tasks(build_config): 544 """Gradle tasks run by |mach android build-geckoview_example|.""" 545 return [ 546 "geckoview_example:assemble{geckoview_example.variant.name}".format( 547 geckoview_example=build_config.geckoview_example 548 ), 549 "geckoview_example:bundle{geckoview_example.variant.name}".format( 550 geckoview_example=build_config.geckoview_example 551 ), 552 "geckoview:assemble{geckoview.variant.name}AndroidTest".format( 553 geckoview=build_config.geckoview 554 ), 555 "test_runner:assemble{geckoview.variant.name}".format( 556 geckoview=build_config.geckoview 557 ), 558 "test_runner:bundle{geckoview.variant.name}".format( 559 geckoview=build_config.geckoview 560 ), 561 ] 562 563 564 set_config( 565 "GRADLE_ANDROID_BUILD_GECKOVIEW_EXAMPLE_TASKS", 566 gradle_android_build_geckoview_example_tasks, 567 ) 568 569 570 @depends(gradle_android_build_config) 571 def gradle_android_compile_all_tasks(build_config): 572 """Gradle tasks run by |mach android compile-all|. 573 574 This is the list of all compile* tasks output by `gradlew tasks`. 575 Some of those tasks names are shared between multiple projects, for instance passing compileSources to Gradle will trigger all of: 576 - geckoview:compileSources 577 - geckoview_example:compileSources 578 - test_runner:compileSources 579 - messaging_example:compileSources 580 - port_messaging_example:compileSources 581 """ 582 583 def capitalize(s): 584 # str.capitalize lower cases trailing letters. 585 if s: 586 return s[0].upper() + s[1:] 587 else: 588 return s 589 590 buildType = capitalize(build_config.geckoview.variant.buildType) 591 592 tasks = [ 593 f"compileJava", 594 f"compileTestJava", 595 f"compileKotlin", 596 f"compileTestKotlin", 597 ] 598 599 # Apps without product flavors (GeckoView, Fenix) use just `buildType` in task names 600 tasks += [ 601 f"compile{buildType}Sources", 602 f"compile{buildType}UnitTestSources", 603 ] 604 605 # Apps with product flavors include `flavor` name and `buildType` in task names 606 for flavor in ["Focus", "Klar"]: 607 tasks += [ 608 f"compile{flavor}{buildType}Sources", 609 f"compile{flavor}{buildType}UnitTestSources", 610 ] 611 612 # These tasks do not appear to have a Release variant 613 if buildType == "Debug": 614 tasks += [f"compile{buildType}AndroidTestSources"] 615 616 for flavor in ["Focus", "Klar"]: 617 tasks += [f"compile{flavor}{buildType}AndroidTestSources"] 618 619 for app in ["Gecko", "System"]: 620 tasks += [ 621 f"compile{app}{buildType}Sources", 622 f"compile{app}{buildType}UnitTestSources", 623 f"compile{app}{buildType}AndroidTestSources", 624 ] 625 626 return tasks 627 628 629 set_config( 630 "GRADLE_ANDROID_COMPILE_ALL_TASKS", 631 gradle_android_compile_all_tasks, 632 ) 633 634 635 @depends(gradle_android_build_config) 636 def gradle_android_install_geckoview_test_runner_tasks(build_config): 637 """Gradle tasks run by |mach android install-geckoview-test_runner|.""" 638 return [ 639 "test_runner:install{geckoview.variant.name}".format( 640 geckoview=build_config.geckoview 641 ), 642 ] 643 644 645 set_config( 646 "GRADLE_ANDROID_INSTALL_GECKOVIEW_TEST_RUNNER_TASKS", 647 gradle_android_install_geckoview_test_runner_tasks, 648 ) 649 650 651 @depends(gradle_android_build_config) 652 def gradle_android_install_geckoview_test_tasks(build_config): 653 """Gradle tasks run by |mach android install-geckoview-test|.""" 654 return [ 655 "geckoview:install{geckoview.variant.name}AndroidTest".format( 656 geckoview=build_config.geckoview 657 ), 658 ] 659 660 661 set_config( 662 "GRADLE_ANDROID_INSTALL_GECKOVIEW_TEST_TASKS", 663 gradle_android_install_geckoview_test_tasks, 664 ) 665 666 667 @depends(gradle_android_build_config) 668 def gradle_android_install_geckoview_example_tasks(build_config): 669 """Gradle tasks run by |mach android install-geckoview_example|.""" 670 return [ 671 "geckoview_example:install{geckoview_example.variant.name}".format( 672 geckoview_example=build_config.geckoview_example 673 ), 674 ] 675 676 677 set_config( 678 "GRADLE_ANDROID_INSTALL_GECKOVIEW_EXAMPLE_TASKS", 679 gradle_android_install_geckoview_example_tasks, 680 ) 681 682 683 @depends( 684 gradle_android_api_lint_tasks, 685 gradle_android_format_lint_check_tasks, 686 gradle_android_checkstyle_tasks, 687 ) 688 @imports(_from="itertools", _import="chain") 689 def gradle_android_dependencies_tasks(*tasks): 690 """Gradle tasks run by |mach android dependencies|.""" 691 692 # The union, plus a bit more, of all of the Gradle tasks 693 # invoked by the android-* automation jobs. 694 return list(t for t in chain(*tasks)) 695 696 697 set_config("GRADLE_ANDROID_DEPENDENCIES_TASKS", gradle_android_dependencies_tasks) 698 699 700 # Automation uses this to change log levels, not use the daemon, and use 701 # offline mode. 702 option(env="GRADLE_FLAGS", default="", help="Flags to pass to Gradle") 703 704 705 @depends("GRADLE_FLAGS") 706 def gradle_flags(value): 707 return value[0] if value else "" 708 709 710 set_config("GRADLE_FLAGS", gradle_flags) 711 712 # Automation will set this to (file:///path/to/local, ...) via the mozconfig. 713 # Local developer default is (maven.google.com). 714 option( 715 env="GRADLE_MAVEN_REPOSITORIES", 716 nargs="+", 717 default=( 718 "https://maven.mozilla.org/maven2/", 719 "https://maven.google.com/", 720 "https://repo.maven.apache.org/maven2/", 721 "https://plugins.gradle.org/m2/", 722 ), 723 help="Comma-separated URLs of Maven repositories containing Gradle dependencies", 724 ) 725 726 option( 727 "--allow-insecure-gradle-repositories", 728 help="Gradle is allowed to connect to insecure Maven repositories", 729 ) 730 731 set_config( 732 "ALLOW_INSECURE_GRADLE_REPOSITORIES", 733 True, 734 when="--allow-insecure-gradle-repositories", 735 ) 736 737 option( 738 "--download-all-gradle-dependencies", 739 help="Download all dependencies, even those that are conditionally used", 740 ) 741 742 set_config( 743 "DOWNLOAD_ALL_GRADLE_DEPENDENCIES", 744 True, 745 when="--download-all-gradle-dependencies", 746 ) 747 748 749 @depends(application_services, "GRADLE_MAVEN_REPOSITORIES") 750 @imports(_from="os.path", _import="isdir") 751 def gradle_maven_repositories(app_services_location, values): 752 if not values: 753 die("GRADLE_MAVEN_REPOSITORIES must not be empty") 754 if not all(values): 755 die("GRADLE_MAVEN_REPOSITORIES entries must not be empty") 756 757 # Prepend the location of the custom a-s location 758 values = (f"file://{app_services_location}",) + values 759 return values 760 761 762 set_config("GRADLE_MAVEN_REPOSITORIES", gradle_maven_repositories) 763 764 765 @imports(_from="sys", _import="prefix") 766 def gradle_glean_parser_venv(): 767 return prefix 768 769 770 set_config("GRADLE_GLEAN_PARSER_VENV", gradle_glean_parser_venv())