├── .gitattributes ├── .github ├── dco.yml ├── dependabot.yml ├── renovate.json5 └── workflows │ ├── build-verification.yml │ ├── combine-prs.yml │ ├── submit-github-dependency-graph.yml │ └── wrapper-upgrade-execution.yml ├── .gitignore ├── LICENSE ├── README.md ├── build.gradle.kts ├── buildSrc ├── build.gradle.kts ├── settings.gradle.kts └── src │ └── main │ └── kotlin │ └── CreateGitTag.kt ├── config └── codenarc │ └── codenarc.xml ├── gradle.properties ├── gradle ├── libs.versions.toml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── release ├── changes.md ├── distribution │ └── NOTICE └── version.txt ├── settings.gradle.kts └── src ├── main ├── groovy │ └── org │ │ └── gradle │ │ └── android │ │ ├── AndroidCacheFixPlugin.groovy │ │ ├── AndroidIssue.groovy │ │ ├── Versions.groovy │ │ ├── Warnings.groovy │ │ ├── WarningsService.groovy │ │ └── workarounds │ │ ├── BundleLibraryClassesWorkaround.groovy │ │ ├── CompileLibraryResourcesWorkaround.groovy │ │ ├── DataBindingMergeDependencyArtifactsWorkaround.groovy │ │ ├── JdkImageWorkaround.groovy │ │ ├── LibraryJniLibsWorkaround.groovy │ │ ├── MergeNativeLibsWorkaround.groovy │ │ ├── MergeSourceSetFoldersWorkaround.groovy │ │ ├── PackageForUnitTestWorkaround.groovy │ │ ├── StripDebugSymbolsWorkaround.groovy │ │ ├── SystemPropertiesCompat.groovy │ │ ├── Workaround.groovy │ │ └── ZipMergingTaskWorkaround.groovy └── java │ └── org │ └── gradle │ └── android │ └── VersionNumber.java └── test ├── groovy └── org │ └── gradle │ └── android │ ├── AbstractTest.groovy │ ├── CodeSnippets.groovy │ ├── CompileLibraryResourcesWorkaroundTest.groovy │ ├── ConfigurationCachingTest.groovy │ ├── CrossVersionOutcomeAndRelocationTest.groovy │ ├── JdkImageWorkaroundDescriptorTest.groovy │ ├── JdkImageWorkaroundTest.groovy │ ├── MergeJavaResourcesWorkaroundTest.groovy │ ├── MultiVersionTest.groovy │ ├── PluginApplicationTest.groovy │ ├── PluginBlockTest.groovy │ ├── RerunTasksTest.groovy │ ├── SimpleAndroidApp.groovy │ ├── TaskAvoidanceTest.groovy │ ├── TestVersions.groovy │ ├── VersionsTest.groovy │ └── WorkaroundTest.groovy └── resources ├── SpockConfig.groovy ├── expectedOutcomes ├── 7.0_outcomes.json ├── 7.1_outcomes.json ├── 7.2_outcomes.json ├── 7.3_outcomes.json ├── 7.4_outcomes.json ├── 8.0_outcomes.json ├── 8.10_outcomes.json ├── 8.11_outcomes.json ├── 8.12_outcomes.json ├── 8.1_outcomes.json ├── 8.2_outcomes.json ├── 8.3_outcomes.json ├── 8.4_outcomes.json ├── 8.5_outcomes.json ├── 8.6_outcomes.json ├── 8.7_outcomes.json ├── 8.8_outcomes.json └── 8.9_outcomes.json └── versions.json /.gitattributes: -------------------------------------------------------------------------------- 1 | *.bat text eol=crlf 2 | -------------------------------------------------------------------------------- /.github/dco.yml: -------------------------------------------------------------------------------- 1 | # Disable sign-off checking for members of the Gradle GitHub organization 2 | require: 3 | members: false 4 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | registries: 3 | gradle-plugin-portal: 4 | type: maven-repository 5 | url: https://plugins.gradle.org/m2 6 | username: dummy # Required by dependabot 7 | password: dummy # Required by dependabot 8 | updates: 9 | - package-ecosystem: "gradle" 10 | directory: "/" 11 | registries: 12 | - gradle-plugin-portal 13 | schedule: 14 | interval: "daily" 15 | time: "02:00" 16 | # See libs.versions.toml for explanations 17 | ignore: 18 | - dependency-name: "com.android.tools.build:gradle" 19 | versions: ["[8.2.0,)"] 20 | - package-ecosystem: "github-actions" 21 | directory: "/" 22 | schedule: 23 | interval: "daily" 24 | time: "02:00" 25 | -------------------------------------------------------------------------------- /.github/renovate.json5: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:recommended", 5 | "github>gradle/renovate-agent//presets/dv.json5", 6 | ":disableDependencyDashboard", 7 | ], 8 | "ignorePresets": [ 9 | // Ignore for versions.json to be parsed (inherited from config:recommended) 10 | ":ignoreModulesAndTests", 11 | ], 12 | "branchPrefix": "renovatebot/", 13 | // See https://docs.renovatebot.com/modules/manager/regex/ 14 | // Dependabot is used for all other updates. 15 | "enabledManagers": ["custom.regex"], 16 | "customManagers": [ 17 | { 18 | // Matches AGP versions in files with custom patterns 19 | customType: "regex", 20 | fileMatch: [ 21 | "src/test/resources/versions\\.json", 22 | "gradle\\.properties", 23 | ], 24 | "matchStrings": [ 25 | // In versions.json, matches keys with a list value, e.g. "8.9.0": [ 26 | "\\s*?\"(?\\S+?)\": *\\[", 27 | // In gradle.properties, matches a specific property's value 28 | "org\\.gradle\\.android\\.latestKnownAgpVersion=(?\\S+?)(?:\\s|$)", 29 | ], 30 | "datasourceTemplate": "maven", 31 | "versioningTemplate": "maven", 32 | "depNameTemplate": "com.android.tools.build:gradle", 33 | "registryUrlTemplate": "https://dl.google.com/dl/android/maven2/", 34 | }, 35 | ], 36 | // Ensure patches to older minors are opened, even if a newer minor is available 37 | // In versions.json, means older minors will still be checked for a newer patch 38 | "separateMinorPatch": true, 39 | "packageRules": [ 40 | { 41 | // In versions.json, disable bumps of major/minor, which should be added as new properties 42 | "matchDepNames": ["com.android.tools.build:gradle"], 43 | "matchUpdateTypes": ["major", "minor"], 44 | "matchFileNames": ["src/test/resources/versions\\.json"], 45 | "enabled": false, 46 | }, 47 | { 48 | // In gradle.properties, allow unstable versions 49 | "matchDepNames": ["com.android.tools.build:gradle"], 50 | "matchFileNames": ["gradle\\.properties"], 51 | "ignoreUnstable": false, 52 | }, 53 | { 54 | // Group changes about AGP versions 55 | "matchFileNames": [ 56 | "src/test/resources/versions\\.json", 57 | "gradle\\.properties", 58 | ], 59 | "commitMessageTopic": "tested AGP versions", 60 | "groupName": "tested AGP versions", 61 | }, 62 | ], 63 | } 64 | -------------------------------------------------------------------------------- /.github/workflows/build-verification.yml: -------------------------------------------------------------------------------- 1 | name: Verify Build 2 | 3 | on: 4 | push: 5 | branches: [ main, citest ] 6 | pull_request: 7 | workflow_dispatch: 8 | 9 | jobs: 10 | generate_versions: 11 | name: Generate versions 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | - id: setup-matrix 16 | shell: bash 17 | run: | 18 | set -euo pipefail 19 | json_to_matrix() { 20 | file="src/test/resources/versions.json" 21 | jq -cM '.testedVersions | keys' "$file" | sed -e 's/\./_/g' -e 's/-/_/g' 22 | } 23 | json_to_matrix 24 | echo "matrix=$(json_to_matrix)" >> $GITHUB_OUTPUT 25 | outputs: 26 | matrix: ${{ steps.setup-matrix.outputs.matrix }} 27 | 28 | sanity_check: 29 | name: Sanity check 30 | runs-on: ubuntu-latest 31 | steps: 32 | - uses: actions/checkout@v4 33 | - uses: actions/setup-java@v4 34 | with: 35 | java-version: 21 36 | distribution: 'temurin' 37 | - name: Set up Gradle 38 | uses: gradle/actions/setup-gradle@v4 39 | with: 40 | develocity-access-key: ${{ secrets.DV_SOLUTIONS_ACCESS_KEY }} 41 | - name: Run sanityCheck 42 | run: ./gradlew sanityCheck -Porg.gradle.java.installations.auto-download=false 43 | 44 | tests: 45 | name: Tests 46 | runs-on: ubuntu-latest 47 | steps: 48 | - uses: actions/checkout@v4 49 | - uses: actions/setup-java@v4 50 | with: 51 | java-version: 21 52 | distribution: 'temurin' 53 | - name: Set up Gradle 54 | uses: gradle/actions/setup-gradle@v4 55 | with: 56 | develocity-access-key: ${{ secrets.DV_SOLUTIONS_ACCESS_KEY }} 57 | - name: Run unit tests 58 | run: >- 59 | ./gradlew test 60 | -x signPluginMavenPublication 61 | -x signAndroidCacheFixPluginPluginMarkerMavenPublication 62 | -Porg.gradle.java.installations.auto-download=false 63 | -Dpts.mode=$PTS_MODE 64 | env: 65 | PTS_MODE: "${{ github.ref_name == 'main' && 'REMAINING_TESTS' || 'RELEVANT_TESTS' }}" 66 | 67 | android_version_tests: 68 | name: Android version tests 69 | needs: [ generate_versions, sanity_check ] 70 | runs-on: ubuntu-latest 71 | strategy: 72 | fail-fast: false 73 | matrix: 74 | versions: ${{ fromJson(needs.generate_versions.outputs.matrix) }} 75 | steps: 76 | - uses: actions/checkout@v4 77 | - name: Setup ZULU_JDK 78 | uses: actions/setup-java@v4 79 | with: 80 | java-version: 11.0.12 81 | distribution: 'zulu' 82 | - name: Set ZULU_JDK environment variable 83 | run: | 84 | echo "ZULU_JDK=$JAVA_HOME" >> $GITHUB_ENV 85 | - name: Setup ZULU_ALT_JDK 86 | uses: actions/setup-java@v4 87 | with: 88 | java-version: 11.0.13 89 | distribution: 'zulu' 90 | - name: Set ZULU_ALT_JDK environment variable 91 | run: | 92 | echo "ZULU_ALT_JDK=$JAVA_HOME" >> $GITHUB_ENV 93 | - name: Set up Java 11 94 | uses: actions/setup-java@v4 95 | with: 96 | java-version: 11 97 | distribution: 'temurin' 98 | - name: Set up Java 17 99 | uses: actions/setup-java@v4 100 | with: 101 | java-version: 17 102 | distribution: 'temurin' 103 | - name: Set up Java 21 104 | uses: actions/setup-java@v4 105 | with: 106 | java-version: 21 107 | distribution: 'temurin' 108 | - name: Set up Gradle 109 | uses: gradle/actions/setup-gradle@v4 110 | with: 111 | develocity-access-key: ${{ secrets.DV_SOLUTIONS_ACCESS_KEY }} 112 | - name: Run integration tests 113 | run: >- 114 | ./gradlew testAndroid${{ matrix.versions }} 115 | -x signPluginMavenPublication 116 | -x signAndroidCacheFixPluginPluginMarkerMavenPublication 117 | -Porg.gradle.java.installations.auto-download=false 118 | -Dpts.mode=$PTS_MODE 119 | env: 120 | PTS_MODE: "${{ github.ref_name == 'main' && 'REMAINING_TESTS' || 'RELEVANT_TESTS' }}" 121 | -------------------------------------------------------------------------------- /.github/workflows/combine-prs.yml: -------------------------------------------------------------------------------- 1 | name: Combine PRs 2 | 3 | on: 4 | schedule: 5 | - cron: '0 4 * * *' 6 | workflow_dispatch: 7 | 8 | # The minimum permissions required to run this Action 9 | permissions: 10 | contents: write 11 | pull-requests: write 12 | checks: read 13 | 14 | jobs: 15 | combine-prs: 16 | if: github.repository == 'gradle/android-cache-fix-gradle-plugin' 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: github/combine-prs@v5.2.0 20 | with: 21 | branch_regex: ^(dependa|wrapper|renovate)bot\/.*$ 22 | github_token: ${{ secrets.GH_BOT_GITHUB_TOKEN }} 23 | -------------------------------------------------------------------------------- /.github/workflows/submit-github-dependency-graph.yml: -------------------------------------------------------------------------------- 1 | name: Submit Dependency Graph 2 | on: 3 | workflow_dispatch: 4 | push: 5 | branches: 6 | - main 7 | 8 | permissions: 9 | contents: write 10 | 11 | jobs: 12 | generate-and-submit: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v4 16 | - uses: actions/setup-java@v4 17 | with: 18 | distribution: temurin 19 | java-version: 21 20 | - name: Submit dependency graph 21 | uses: gradle/actions/dependency-submission@v4 22 | with: 23 | develocity-access-key: ${{ secrets.DV_SOLUTIONS_ACCESS_KEY }} 24 | env: 25 | DEPENDENCY_GRAPH_EXCLUDE_CONFIGURATIONS: '.*[Tt]est(Compile|Runtime)Classpath' 26 | -------------------------------------------------------------------------------- /.github/workflows/wrapper-upgrade-execution.yml: -------------------------------------------------------------------------------- 1 | name: Execute Wrapper Upgrade 2 | 3 | on: 4 | schedule: 5 | - cron: '0 2 * * *' 6 | workflow_dispatch: 7 | 8 | jobs: 9 | upgrade_wrapper: 10 | name: Execution 11 | runs-on: ubuntu-latest 12 | if: github.repository == 'gradle/android-cache-fix-gradle-plugin' 13 | steps: 14 | - name: Set up Git configuration 15 | env: 16 | TOKEN: ${{ secrets.GITHUB_TOKEN }} 17 | run: git config --global url."https://unused-username:${TOKEN}@github.com/".insteadOf "https://github.com/" 18 | - name: Import GPG key 19 | uses: crazy-max/ghaction-import-gpg@e89d40939c28e39f97cf32126055eeae86ba74ec 20 | with: 21 | gpg_private_key: ${{ secrets.GH_BOT_PGP_PRIVATE_KEY }} 22 | passphrase: ${{ secrets.GH_BOT_PGP_PASSPHRASE }} 23 | git_user_signingkey: true 24 | git_commit_gpgsign: true 25 | git_config_global: true 26 | - name: Checkout 27 | uses: actions/checkout@v4 28 | - name: Set up JDK 21 29 | uses: actions/setup-java@v4 30 | with: 31 | java-version: '21' 32 | distribution: 'temurin' 33 | - name: Set up Gradle 34 | uses: gradle/actions/setup-gradle@v4 35 | with: 36 | develocity-access-key: ${{ secrets.DV_SOLUTIONS_ACCESS_KEY }} 37 | - name: Upgrade Wrappers 38 | run: ./gradlew clean upgradeGradleWrapperAll --continue -Porg.gradle.java.installations.auto-download=false 39 | env: 40 | WRAPPER_UPGRADE_GIT_TOKEN: ${{ secrets.GITHUB_TOKEN }} 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Gradle 2 | # ------ 3 | .gradle/ 4 | build/ 5 | 6 | # IDEA 7 | # ---- 8 | .idea/ 9 | *.iml 10 | *.ipr 11 | *.iws 12 | out/ 13 | 14 | # Eclipse 15 | # ------- 16 | *.classpath 17 | *.project 18 | *.settings 19 | bin/ 20 | 21 | # macOS 22 | # ---- 23 | .DS_Store 24 | 25 | # Logs 26 | # ---- 27 | *.log 28 | 29 | # Android Studio 30 | local.properties -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > _This repository is maintained by the Develocity Solutions team, as one of several publicly available repositories:_ 2 | > - _[Android Cache Fix Gradle Plugin][android-cache-fix-plugin] (this repository)_ 3 | > - _[Common Custom User Data Gradle Plugin][ccud-gradle-plugin]_ 4 | > - _[Common Custom User Data Maven Extension][ccud-maven-extension]_ 5 | > - _[Develocity Build Configuration Samples][develocity-build-config-samples]_ 6 | > - _[Develocity Build Validation Scripts][develocity-build-validation-scripts]_ 7 | > - _[Develocity Open Source Projects][develocity-oss-projects]_ 8 | > - _[Quarkus Build Caching Extension][quarkus-build-caching-extension]_ 9 | 10 | 11 | # Android Cache Fix Gradle Plugin 12 | 13 | [![Verify Build](https://github.com/gradle/android-cache-fix-gradle-plugin/actions/workflows/build-verification.yml/badge.svg?branch=main)](https://github.com/gradle/android-cache-fix-gradle-plugin/actions/workflows/build-verification.yml) 14 | [![Plugin Portal](https://img.shields.io/maven-metadata/v?metadataUrl=https://plugins.gradle.org/m2/gradle/plugin/org/gradle/android/android-cache-fix-gradle-plugin/maven-metadata.xml&label=Plugin%20Portal)](https://plugins.gradle.org/plugin/org.gradle.android.cache-fix) 15 | [![Revved up by Develocity](https://img.shields.io/badge/Revved%20up%20by-Develocity-06A0CE?logo=Gradle&labelColor=02303A)](https://ge.solutions-team.gradle.com/scans) 16 | 17 | 18 | Some Android plugin versions have issues with Gradle's build cache feature. When applied to an Android project this plugin applies workarounds for these issues based on the Android plugin and Gradle versions. For other versions, please see [older versions.](#older-android-gradle-plugin-versions) 19 | 20 | * Supported Gradle versions: 7.0+ 21 | * Supported Android Gradle Plugin versions: 7.0+, including alpha, beta, and rc versions 22 | * Supported Kotlin versions: 1.7.0+ 23 | 24 | We only test against the latest patch versions of each minor version of Android Gradle Plugin. This means that although it may work perfectly well with an older patch version (say 7.0.1), we do not test against these older patch versions, so the latest patch version is the only version from that minor release that we technically support. 25 | 26 | The Android cache fix plugin is compatible with the [Gradle Configuration Cache](https://docs.gradle.org/current/userguide/configuration_cache.html#header) when used in conjunction with Android Gradle Plugin 4.2.0 and above. Using the configuration cache with earlier versions of the Android Gradle Plugin is not supported. 27 | 28 | ## Should I use this? 29 | Take a look at the [list of issues](#list-of-issues) especially [unresolved issues](#unresolved-issues). If any of these apply to your project, you can use this plugin to solve them. 30 | 31 | ## How can I discover issues? 32 | You can discover issues by using the task input comparison tool in Develocity. More information about [how to diagnose cache misses here](https://docs.gradle.com/enterprise/tutorials/task-inputs-comparison/). You can compare the inputs of a build that seeds the build cache - typically CI - with a build that consumes from the build cache like a local developer build. 33 | If you discover an issue related to the Android Gradle Plugin, please file an issue in the [Android Bug Tracker](https://source.android.com/setup/contribute/report-bugs). You can also file an [issue here](https://github.com/gradle/android-cache-fix-gradle-plugin/issues) and we can see if a workaround is possible. 34 | 35 | ## Applying the plugin 36 | 37 | This plugin should be applied anywhere the `com.android.application` or `com.android.library` plugins are applied. We recommend adding the plugin to your project's [conventions plugin](https://docs.gradle.org/current/samples/sample_convention_plugins.html). 38 | 39 |
40 | Kotlin 41 |
42 | 43 | ```kotlin 44 | // in build.grade.kts for convention plugin build 45 | dependencies { 46 | // ... 47 | implementation("org.gradle.android.cache-fix:org.gradle.android.cache-fix.gradle.plugin:3.0.1") 48 | // ... 49 | } 50 | 51 | // in com.myconventions.build.gradle.kts 52 | plugins { 53 | id("com.android.application") // or "com.android.library" 54 | // Add this next line to your existing convention plugin. 55 | id("org.gradle.android.cache-fix") 56 | } 57 | ``` 58 |
59 | 60 |
61 | Groovy 62 |
63 | 64 | ```groovy 65 | // in build.grade for convention plugin build 66 | dependencies { 67 | // ... 68 | implementation("org.gradle.android.cache-fix:org.gradle.android.cache-fix.gradle.plugin:3.0.1") 69 | // ... 70 | } 71 | 72 | // in com.myconventions.build.gradle 73 | plugins { 74 | id 'com.android.application' // or 'com.android.library' 75 | // Add this next line to your existing convention plugin. 76 | id 'org.gradle.android.cache-fix' 77 | } 78 | ``` 79 | 80 |
81 | 82 | If you are not using convention plugins and would like a quick way of testing the plugin you can alternatively place it in the root project's build.gradle (change '3.0.1' to the latest version of the cache fix plugin 83 | [here](https://plugins.gradle.org/plugin/org.gradle.android.cache-fix)). We discourage this approach because it uses [cross project configuration](https://docs.gradle.org/current/userguide/sharing_build_logic_between_subprojects.html#sec:convention_plugins_vs_cross_configuration). 84 | 85 |
86 | Kotlin 87 |
88 | 89 | ```kotlin 90 | plugins { 91 | id("org.gradle.android.cache-fix") version "3.0.1" apply false 92 | } 93 | 94 | subprojects { 95 | plugins.withType() { 96 | apply(plugin = "org.gradle.android.cache-fix") 97 | } 98 | } 99 | ``` 100 |
101 | 102 |
103 | Groovy 104 |
105 | 106 | ```groovy 107 | plugins { 108 | id "org.gradle.android.cache-fix" version "3.0.1" apply false 109 | } 110 | 111 | subprojects { 112 | plugins.withType(com.android.build.gradle.api.AndroidBasePlugin) { 113 | project.apply plugin: "org.gradle.android.cache-fix" 114 | } 115 | } 116 | ``` 117 |
118 | 119 | ## List of issues 120 | 121 | You can take a look at the list of issues that the plugin fixes by looking at the classes in [`org.gradle.android.workarounds`](https://github.com/gradle/android-cache-fix-gradle-plugin/blob/master/src/main/groovy/org/gradle/android/workarounds). It contains a number of `Workaround` implementations annotated with `@AndroidIssue`. The Javadoc has a short description of the problem, and the annotation gives information about when the problem was introduced, what is the first version of the Android plugin that fixes it, and there's a link to the issue on Android's issue tracker: 122 | 123 | ```groovy 124 | /** 125 | * Fix {@link org.gradle.api.tasks.compile.CompileOptions#getBootClasspath()} introducing relocatability problems for {@link AndroidJavaCompile}. 126 | */ 127 | @AndroidIssue(introducedIn = "3.0.0", fixedIn = "3.1.0-alpha06", link = "https://issuetracker.google.com/issues/68392933") 128 | static class AndroidJavaCompile_BootClasspath_Workaround implements Workaround { 129 | // ... 130 | } 131 | ``` 132 | 133 | ### Unresolved Issues 134 | 135 | ***Please vote for the linked issues if you are experiencing them in your project.*** 136 | 137 | Fixed by the Android Cache Fix plugin, but unresolved in any current or upcoming preview release of the Android Gradle Plugin: 138 | 139 | Not fixed by the Android Cache Fix plugin since it has no workaround: 140 | 141 | * CompileLibraryResourcesTask outputs contain absolute paths: https://issuetracker.google.com/issues/282761461 142 | 143 | Not fixed by the Android Cache Fix plugin since it has no workaround but is fixed in Android Gradle Plugin 8.0.0 or newer: 144 | 145 | * MergeResources is not relocatable: https://issuetracker.google.com/issues/246529491 146 | 147 | ### Room 148 | The Room annotation processor causes cache misses: https://issuetracker.google.com/issues/132245929. 149 | To work around this issue, please apply the [Room Gradle Plugin](https://developer.android.com/jetpack/androidx/releases/room#gradle-plugin). 150 | 151 | 152 | ## Implementation Notes 153 | 154 | ### MergeNativeLibs, StripDebugSymbols, MergeJavaResources, MergeSourceSetFolders, BundleLibraryClassesJar, DataBindingMergeDependencyArtifacts, LibraryJniLibs and ZipMerging Workarounds 155 | 156 | It has been observed that caching the `MergeNativeLibsTask`, `StripDebugSymbols`, `MergeSourceSetFolders`, `BundleLibraryClassesJar`, `DataBindingMergeDependencyArtifacts`, `LibraryJniLibs` and `ZipMergingTask` tasks rarely provide any significant positive avoidance savings. In fact, they frequently provide negative savings, especially when fetched from a remote cache node. As such, these workarounds disable caching for these tasks. 157 | 158 | ### Older Android Gradle Plugin Versions 159 | 160 | Use Android Cache Fix Plugin 2.4.6 when using an older Android Gradle Plugin version. 161 | 162 | * Supported Gradle versions: 5.4.1+ 163 | * Supported Android Gradle Plugin versions: 3.5.4, 3.6.4, 4.0.1, 4.1.3, 4.2.2 164 | 165 | ### Older Kotlin Gradle Plugin Versions 166 | Use Android Cache Fix Plugin 2.6.0 when using an older Kotlin Gradle Plugin version. 167 | * Supported Kotlin versions: \[1.3.72-1.5.32\] 168 | 169 | ## Learn more 170 | 171 | Visit our website to learn more about [Develocity][develocity]. 172 | 173 | ## License 174 | 175 | The Android Cache Fix Gradle plugin is open-source software released under the [Apache 2.0 License][apache-license]. 176 | 177 | [android-cache-fix-plugin]: https://github.com/gradle/android-cache-fix-gradle-plugin 178 | [ccud-gradle-plugin]: https://github.com/gradle/common-custom-user-data-gradle-plugin 179 | [ccud-maven-extension]: https://github.com/gradle/common-custom-user-data-maven-extension 180 | [develocity-build-config-samples]: https://github.com/gradle/develocity-build-config-samples 181 | [develocity-build-validation-scripts]: https://github.com/gradle/develocity-build-validation-scripts 182 | [develocity-oss-projects]: https://github.com/gradle/develocity-oss-projects 183 | [quarkus-build-caching-extension]: https://github.com/gradle/quarkus-build-caching-extension 184 | [develocity]: https://gradle.com/develocity 185 | [apache-license]: https://www.apache.org/licenses/LICENSE-2.0.html 186 | -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | import com.gradle.develocity.agent.gradle.test.PredictiveTestSelectionProfile.FAST 2 | import com.gradle.develocity.agent.gradle.test.PredictiveTestSelectionProfile.STANDARD 3 | import groovy.json.JsonSlurper 4 | 5 | // Upgrade transitive dependencies in plugin classpath 6 | buildscript { 7 | repositories { 8 | gradlePluginPortal() 9 | } 10 | dependencies { 11 | constraints { 12 | // Dependency of 'com.github.breadmoirai.github-release:2.5.2' 13 | classpath(libs.okio) // CVE-2023-3635 14 | } 15 | } 16 | } 17 | 18 | plugins { 19 | id("groovy") 20 | id("java-gradle-plugin") 21 | id("maven-publish") 22 | id("signing") 23 | id("codenarc") 24 | alias(libs.plugins.gradle.pluginPublish) 25 | alias(libs.plugins.github.release) 26 | alias(libs.plugins.gradle.wrapperUpgrade) 27 | } 28 | 29 | val releaseVersion = releaseVersion() 30 | val releaseNotes = releaseNotes() 31 | val isCI = providers.environmentVariable("CI").isPresent 32 | 33 | group = "org.gradle.android" 34 | version = releaseVersion.get() 35 | description = "A Gradle plugin to fix Android caching problems" 36 | 37 | repositories { 38 | google() 39 | mavenCentral() 40 | } 41 | 42 | dependencies { 43 | compileOnly(gradleApi()) 44 | compileOnly(libs.android.gradlePlugin) 45 | compileOnly(libs.android.common) 46 | compileOnly(libs.android.sdkCommon) 47 | implementation(libs.guava) 48 | 49 | testImplementation(gradleTestKit()) 50 | testImplementation(libs.android.gradlePlugin) 51 | testImplementation(platform(libs.spock.bom)) 52 | testImplementation(libs.spock.core) { exclude(group = "org.codehaus.groovy") } 53 | testImplementation(libs.spock.junit4) { exclude(group = "org.codehaus.groovy") } 54 | testImplementation(libs.junit.jupiter.api) 55 | } 56 | 57 | wrapperUpgrade { 58 | gradle { 59 | create("android-cache-fix-gradle-plugin") { 60 | repo = "gradle/android-cache-fix-gradle-plugin" 61 | } 62 | } 63 | } 64 | 65 | java { 66 | toolchain { 67 | // AGP 7+ only supports JDK 11+ 68 | languageVersion = JavaLanguageVersion.of(11) 69 | } 70 | } 71 | 72 | // Main plugin publishing metadata 73 | gradlePlugin { 74 | website = "https://github.com/gradle/android-cache-fix-gradle-plugin" 75 | vcsUrl = "https://github.com/gradle/android-cache-fix-gradle-plugin" 76 | 77 | plugins { 78 | create("androidCacheFixPlugin") { 79 | id = "org.gradle.android.cache-fix" 80 | displayName = "Gradle Android cache fix plugin" 81 | description = releaseNotes.get() 82 | implementationClass = "org.gradle.android.AndroidCacheFixPlugin" 83 | tags.addAll("android", "cache", "fix") 84 | } 85 | } 86 | } 87 | 88 | // A local repo we publish our library to for testing in order to workaround limitations 89 | // in the TestKit plugin classpath. 90 | val localRepo = layout.buildDirectory.dir("local-repo") 91 | 92 | val isProdPortal = providers.systemProperty("gradle.portal.url").orNull == null 93 | // The legacy groupId gradle.plugin.* is only allowed when the plugin 94 | // has already been published 95 | val pluginGroupId: String = if (isCI && isProdPortal) "gradle.plugin.org.gradle.android" else project.group.toString() 96 | publishing { 97 | publications { 98 | create("pluginMaven") { 99 | groupId = pluginGroupId 100 | pom { 101 | name.set("Android Cache Fix Gradle Plugin") 102 | description.set("A Gradle plugin to workaround cache issues in Android builds") 103 | url.set("https://github.com/gradle/android-cache-fix-gradle-plugin") 104 | licenses { 105 | license { 106 | name.set("Apache-2.0") 107 | url.set("https://www.apache.org/licenses/LICENSE-2.0.txt") 108 | } 109 | } 110 | developers { 111 | developer { 112 | name.set("The Gradle team") 113 | organization.set("Gradle Inc.") 114 | organizationUrl.set("https://gradle.com") 115 | } 116 | } 117 | scm { 118 | developerConnection.set("scm:git:https://github.com/gradle/android-cache-fix-gradle-plugin.git") 119 | url.set("https://github.com/gradle/android-cache-fix-gradle-plugin") 120 | } 121 | } 122 | } 123 | } 124 | repositories { 125 | maven { 126 | url = localRepo.get().asFile.toURI() 127 | } 128 | } 129 | } 130 | 131 | tasks.withType().configureEach { 132 | into(".") { 133 | from(layout.projectDirectory.file("LICENSE")) 134 | from(layout.projectDirectory.dir("release/distribution")) 135 | } 136 | } 137 | 138 | // Configuration common to all test tasks 139 | tasks.withType().configureEach { 140 | dependsOn(tasks.publish) 141 | workingDir = projectDir 142 | systemProperty("local.repo", projectDir.toPath().relativize(localRepo.get().asFile.toPath()).toString()) 143 | systemProperty("pluginGroupId", pluginGroupId) 144 | systemProperty("org.gradle.android.cache-fix.version", version) 145 | useJUnitPlatform() 146 | develocity.testRetry { 147 | maxRetries = if (isCI) 1 else 0 148 | maxFailures = 20 149 | } 150 | } 151 | 152 | tasks.test { 153 | develocity.predictiveTestSelection { 154 | profile = STANDARD 155 | } 156 | } 157 | 158 | val latestVersion = providers.gradleProperty("org.gradle.android.latestKnownAgpVersion") 159 | val testedVersions = readTestedVersions() 160 | 161 | check(latestVersion.get() in testedVersions) { 162 | "The project must be updated to support AGP $latestVersion. Please add it to tested versions." 163 | } 164 | 165 | testedVersions.keys.forEach { androidVersion -> 166 | val versionSpecificTest = tasks.register(androidTestTaskName(androidVersion)) { 167 | description = "Runs the multi-version tests for AGP $androidVersion" 168 | group = "verification" 169 | 170 | systemProperty("org.gradle.android.testVersion", androidVersion) 171 | project.providers.environmentVariable("ZULU_JDK").orNull?.let { 172 | systemProperty("org.gradle.android.java_zulu_path", it) 173 | } 174 | project.providers.environmentVariable("ZULU_ALT_JDK").orNull?.let { 175 | systemProperty("org.gradle.android.java_zulu_alt_path", it) 176 | } 177 | 178 | if (androidVersion >= "8.0.0") { 179 | javaLauncher = javaToolchains.launcherFor { 180 | languageVersion = JavaLanguageVersion.of(17) 181 | } 182 | } 183 | 184 | develocity.predictiveTestSelection { 185 | profile = FAST 186 | } 187 | } 188 | 189 | tasks.check { 190 | dependsOn(versionSpecificTest) 191 | } 192 | } 193 | 194 | fun androidTestTaskName(androidVersion: String): String { 195 | return "testAndroid${normalizeVersion(androidVersion)}" 196 | } 197 | 198 | fun normalizeVersion(version: String): String { 199 | return version.replace("[.\\-]".toRegex(), "_") 200 | } 201 | 202 | // A basic sanity check to run before running all test tasks 203 | tasks.register("sanityCheck") { 204 | dependsOn(tasks.withType(), tasks.validatePlugins) 205 | } 206 | 207 | tasks.withType().configureEach { 208 | failOnWarning = true 209 | enableStricterValidation = true 210 | } 211 | 212 | signing { 213 | // Require publications to be signed when :publishPlugins task is included in the TaskGraph 214 | setRequired({ gradle.taskGraph.hasTask(":publishPlugins") }) 215 | 216 | useInMemoryPgpKeys( 217 | providers.environmentVariable("PGP_SIGNING_KEY").orNull, 218 | providers.environmentVariable("PGP_SIGNING_KEY_PASSPHRASE").orNull 219 | ) 220 | } 221 | 222 | githubRelease { 223 | token(providers.environmentVariable("ANDROID_CACHE_FIX_PLUGIN_GIT_TOKEN").orNull) 224 | owner = "gradle" 225 | repo = "android-cache-fix-gradle-plugin" 226 | releaseName = releaseVersion 227 | tagName = releaseVersion.map { "v$it" } 228 | prerelease = false 229 | overwrite = false 230 | generateReleaseNotes = false 231 | body = releaseNotes 232 | targetCommitish = "main" 233 | } 234 | 235 | val createReleaseTag = tasks.register("createReleaseTag") { 236 | // Ensure tag is created only after successful publishing 237 | mustRunAfter(tasks.publishPlugins) 238 | tagName = githubRelease.tagName.map { it.toString() } 239 | } 240 | 241 | tasks.githubRelease { 242 | dependsOn(createReleaseTag) 243 | } 244 | 245 | tasks.withType().configureEach { 246 | notCompatibleWithConfigurationCache("https://github.com/gradle/gradle/issues/21283") 247 | } 248 | 249 | fun releaseVersion(): Provider { 250 | val releaseVersionFile = layout.projectDirectory.file("release/version.txt") 251 | return providers.fileContents(releaseVersionFile).asText.map { it.trim() } 252 | } 253 | 254 | fun releaseNotes(): Provider { 255 | val releaseNotesFile = layout.projectDirectory.file("release/changes.md") 256 | return providers.fileContents(releaseNotesFile).asText.map { it.trim() } 257 | } 258 | 259 | @Suppress("UNCHECKED_CAST") 260 | fun readTestedVersions(): Map> { 261 | val versionFile = providers.fileContents(layout.projectDirectory.file("src/test/resources/versions.json")) 262 | val json = JsonSlurper().parse(versionFile.asBytes.get()) as Map>> 263 | return json.getValue("testedVersions") 264 | } 265 | -------------------------------------------------------------------------------- /buildSrc/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | `kotlin-dsl` 3 | } 4 | 5 | repositories { 6 | mavenCentral() 7 | } 8 | 9 | java { 10 | toolchain { 11 | languageVersion = JavaLanguageVersion.of(11) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /buildSrc/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("org.gradle.toolchains.foojay-resolver-convention") 3 | } 4 | -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/CreateGitTag.kt: -------------------------------------------------------------------------------- 1 | import org.gradle.api.DefaultTask 2 | import org.gradle.api.model.ObjectFactory 3 | import org.gradle.api.provider.Property 4 | import org.gradle.api.tasks.Input 5 | import org.gradle.api.tasks.Optional 6 | import org.gradle.api.tasks.TaskAction 7 | import org.gradle.process.ExecOperations 8 | import org.gradle.work.DisableCachingByDefault 9 | import javax.inject.Inject 10 | 11 | @DisableCachingByDefault(because = "Produces no cacheable output") 12 | abstract class CreateGitTag @Inject constructor( 13 | private val objects: ObjectFactory, 14 | private val execOperations: ExecOperations 15 | ) : DefaultTask() { 16 | 17 | @get:Input 18 | val tagName: Property = objects.property(String::class.java) 19 | 20 | @get:Input 21 | @get:Optional 22 | val overwriteExisting: Property = objects.property(Boolean::class.java).apply { 23 | value(false) 24 | } 25 | 26 | @TaskAction 27 | fun applyArgbash() { 28 | logger.info("Tagging HEAD as ${tagName.get()}") 29 | execOperations.exec { 30 | val args = mutableListOf("git", "tag") 31 | if (overwriteExisting.get()) { 32 | args.add("-f") 33 | } 34 | args.add(tagName.get()) 35 | commandLine(args) 36 | } 37 | execOperations.exec { 38 | val args = mutableListOf("git", "push", "origin") 39 | if (overwriteExisting.get()) { 40 | args.add("-f") 41 | } 42 | args.add("--tags") 43 | commandLine(args) 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /config/codenarc/codenarc.xml: -------------------------------------------------------------------------------- 1 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.parallel=true 2 | org.gradle.caching=true 3 | org.gradle.configuration-cache=true 4 | org.gradle.jvmargs=-Duser.language=en -Duser.country=US -Dfile.encoding=UTF-8 5 | org.gradle.kotlin.dsl.allWarningsAsErrors=true 6 | 7 | systemProp.pts.enabled=true 8 | 9 | org.gradle.android.latestKnownAgpVersion=8.12.0-alpha03 10 | -------------------------------------------------------------------------------- /gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | # AGP is kept at 8.1 because it includes all referenced classes. 3 | # Integration tests guarantee compatibility with newer AGP versions. 4 | android-gradlePlugin = "8.1.4" 5 | android-sdkBuildTools = "31.10.1" 6 | github-release = "2.5.2" 7 | gradle-pluginPublish = "1.3.1" 8 | gradle-wrapperUpgrade = "0.12" 9 | guava = "33.4.8-jre" 10 | okio = "3.12.0" 11 | # Gradle plugins must use Groovy 3 12 | # https://docs.gradle.org/current/userguide/compatibility.html#groovy 13 | spock = "2.3-groovy-3.0" 14 | 15 | [libraries] 16 | android-common = { module = "com.android.tools:common", version.ref = "android-sdkBuildTools" } 17 | android-gradlePlugin = { module = "com.android.tools.build:gradle", version.ref = "android-gradlePlugin" } 18 | android-sdkCommon = { module = "com.android.tools:sdk-common", version.ref = "android-sdkBuildTools" } 19 | guava = { module = "com.google.guava:guava", version.ref = "guava" } 20 | junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api" } 21 | okio = { module = "com.squareup.okio:okio", version.ref = "okio" } 22 | spock-bom = { module = "org.spockframework:spock-bom", version.ref = "spock" } 23 | spock-core = { module = "org.spockframework:spock-core" } 24 | spock-junit4 = { module = "org.spockframework:spock-junit4" } 25 | 26 | [plugins] 27 | github-release = { id = "com.github.breadmoirai.github-release", version.ref = "github-release" } 28 | gradle-pluginPublish = { id = "com.gradle.plugin-publish", version.ref = "gradle-pluginPublish" } 29 | gradle-wrapperUpgrade = { id = "org.gradle.wrapper-upgrade", version.ref = "gradle-wrapperUpgrade" } 30 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gradle/android-cache-fix-gradle-plugin/3a5c46b0836b62ff4137914f91fce14a3907d22c/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionSha256Sum=7197a12f450794931532469d4ff21a59ea2c1cd59a3ec3f89c035c3c420a6999 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip 5 | networkTimeout=10000 6 | validateDistributionUrl=true 7 | zipStoreBase=GRADLE_USER_HOME 8 | zipStorePath=wrapper/dists 9 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | ############################################################################## 22 | # 23 | # Gradle start up script for POSIX generated by Gradle. 24 | # 25 | # Important for running: 26 | # 27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 28 | # noncompliant, but you have some other compliant shell such as ksh or 29 | # bash, then to run this script, type that shell name before the whole 30 | # command line, like: 31 | # 32 | # ksh Gradle 33 | # 34 | # Busybox and similar reduced shells will NOT work, because this script 35 | # requires all of these POSIX shell features: 36 | # * functions; 37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 39 | # * compound commands having a testable exit status, especially «case»; 40 | # * various built-in commands including «command», «set», and «ulimit». 41 | # 42 | # Important for patching: 43 | # 44 | # (2) This script targets any POSIX shell, so it avoids extensions provided 45 | # by Bash, Ksh, etc; in particular arrays are avoided. 46 | # 47 | # The "traditional" practice of packing multiple parameters into a 48 | # space-separated string is a well documented source of bugs and security 49 | # problems, so this is (mostly) avoided, by progressively accumulating 50 | # options in "$@", and eventually passing that to Java. 51 | # 52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 54 | # see the in-line comments for details. 55 | # 56 | # There are tweaks for specific operating systems such as AIX, CygWin, 57 | # Darwin, MinGW, and NonStop. 58 | # 59 | # (3) This script is generated from the Groovy template 60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 61 | # within the Gradle project. 62 | # 63 | # You can find Gradle at https://github.com/gradle/gradle/. 64 | # 65 | ############################################################################## 66 | 67 | # Attempt to set APP_HOME 68 | 69 | # Resolve links: $0 may be a link 70 | app_path=$0 71 | 72 | # Need this for daisy-chained symlinks. 73 | while 74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 75 | [ -h "$app_path" ] 76 | do 77 | ls=$( ls -ld "$app_path" ) 78 | link=${ls#*' -> '} 79 | case $link in #( 80 | /*) app_path=$link ;; #( 81 | *) app_path=$APP_HOME$link ;; 82 | esac 83 | done 84 | 85 | # This is normally unused 86 | # shellcheck disable=SC2034 87 | APP_BASE_NAME=${0##*/} 88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) 89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit 90 | 91 | # Use the maximum available, or set MAX_FD != -1 to use that value. 92 | MAX_FD=maximum 93 | 94 | warn () { 95 | echo "$*" 96 | } >&2 97 | 98 | die () { 99 | echo 100 | echo "$*" 101 | echo 102 | exit 1 103 | } >&2 104 | 105 | # OS specific support (must be 'true' or 'false'). 106 | cygwin=false 107 | msys=false 108 | darwin=false 109 | nonstop=false 110 | case "$( uname )" in #( 111 | CYGWIN* ) cygwin=true ;; #( 112 | Darwin* ) darwin=true ;; #( 113 | MSYS* | MINGW* ) msys=true ;; #( 114 | NONSTOP* ) nonstop=true ;; 115 | esac 116 | 117 | CLASSPATH="\\\"\\\"" 118 | 119 | 120 | # Determine the Java command to use to start the JVM. 121 | if [ -n "$JAVA_HOME" ] ; then 122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 123 | # IBM's JDK on AIX uses strange locations for the executables 124 | JAVACMD=$JAVA_HOME/jre/sh/java 125 | else 126 | JAVACMD=$JAVA_HOME/bin/java 127 | fi 128 | if [ ! -x "$JAVACMD" ] ; then 129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 130 | 131 | Please set the JAVA_HOME variable in your environment to match the 132 | location of your Java installation." 133 | fi 134 | else 135 | JAVACMD=java 136 | if ! command -v java >/dev/null 2>&1 137 | then 138 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 139 | 140 | Please set the JAVA_HOME variable in your environment to match the 141 | location of your Java installation." 142 | fi 143 | fi 144 | 145 | # Increase the maximum file descriptors if we can. 146 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 147 | case $MAX_FD in #( 148 | max*) 149 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 150 | # shellcheck disable=SC2039,SC3045 151 | MAX_FD=$( ulimit -H -n ) || 152 | warn "Could not query maximum file descriptor limit" 153 | esac 154 | case $MAX_FD in #( 155 | '' | soft) :;; #( 156 | *) 157 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 158 | # shellcheck disable=SC2039,SC3045 159 | ulimit -n "$MAX_FD" || 160 | warn "Could not set maximum file descriptor limit to $MAX_FD" 161 | esac 162 | fi 163 | 164 | # Collect all arguments for the java command, stacking in reverse order: 165 | # * args from the command line 166 | # * the main class name 167 | # * -classpath 168 | # * -D...appname settings 169 | # * --module-path (only if needed) 170 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 171 | 172 | # For Cygwin or MSYS, switch paths to Windows format before running java 173 | if "$cygwin" || "$msys" ; then 174 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 175 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 176 | 177 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 178 | 179 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 180 | for arg do 181 | if 182 | case $arg in #( 183 | -*) false ;; # don't mess with options #( 184 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 185 | [ -e "$t" ] ;; #( 186 | *) false ;; 187 | esac 188 | then 189 | arg=$( cygpath --path --ignore --mixed "$arg" ) 190 | fi 191 | # Roll the args list around exactly as many times as the number of 192 | # args, so each arg winds up back in the position where it started, but 193 | # possibly modified. 194 | # 195 | # NB: a `for` loop captures its iteration list before it begins, so 196 | # changing the positional parameters here affects neither the number of 197 | # iterations, nor the values presented in `arg`. 198 | shift # remove old arg 199 | set -- "$@" "$arg" # push replacement arg 200 | done 201 | fi 202 | 203 | 204 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 205 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 206 | 207 | # Collect all arguments for the java command: 208 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, 209 | # and any embedded shellness will be escaped. 210 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be 211 | # treated as '${Hostname}' itself on the command line. 212 | 213 | set -- \ 214 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 215 | -classpath "$CLASSPATH" \ 216 | -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ 217 | "$@" 218 | 219 | # Stop when "xargs" is not available. 220 | if ! command -v xargs >/dev/null 2>&1 221 | then 222 | die "xargs is not available" 223 | fi 224 | 225 | # Use "xargs" to parse quoted args. 226 | # 227 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 228 | # 229 | # In Bash we could simply go: 230 | # 231 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 232 | # set -- "${ARGS[@]}" "$@" 233 | # 234 | # but POSIX shell has neither arrays nor command substitution, so instead we 235 | # post-process each arg (as a line of input to sed) to backslash-escape any 236 | # character that might be a shell metacharacter, then use eval to reverse 237 | # that process (while maintaining the separation between arguments), and wrap 238 | # the whole thing up as a single "set" statement. 239 | # 240 | # This will of course break if any of these variables contains a newline or 241 | # an unmatched quote. 242 | # 243 | 244 | eval "set -- $( 245 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 246 | xargs -n1 | 247 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 248 | tr '\n' ' ' 249 | )" '"$@"' 250 | 251 | exec "$JAVACMD" "$@" 252 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | @rem SPDX-License-Identifier: Apache-2.0 17 | @rem 18 | 19 | @if "%DEBUG%"=="" @echo off 20 | @rem ########################################################################## 21 | @rem 22 | @rem Gradle startup script for Windows 23 | @rem 24 | @rem ########################################################################## 25 | 26 | @rem Set local scope for the variables with windows NT shell 27 | if "%OS%"=="Windows_NT" setlocal 28 | 29 | set DIRNAME=%~dp0 30 | if "%DIRNAME%"=="" set DIRNAME=. 31 | @rem This is normally unused 32 | set APP_BASE_NAME=%~n0 33 | set APP_HOME=%DIRNAME% 34 | 35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 37 | 38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 40 | 41 | @rem Find java.exe 42 | if defined JAVA_HOME goto findJavaFromJavaHome 43 | 44 | set JAVA_EXE=java.exe 45 | %JAVA_EXE% -version >NUL 2>&1 46 | if %ERRORLEVEL% equ 0 goto execute 47 | 48 | echo. 1>&2 49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 50 | echo. 1>&2 51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 52 | echo location of your Java installation. 1>&2 53 | 54 | goto fail 55 | 56 | :findJavaFromJavaHome 57 | set JAVA_HOME=%JAVA_HOME:"=% 58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 59 | 60 | if exist "%JAVA_EXE%" goto execute 61 | 62 | echo. 1>&2 63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 64 | echo. 1>&2 65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 66 | echo location of your Java installation. 1>&2 67 | 68 | goto fail 69 | 70 | :execute 71 | @rem Setup the command line 72 | 73 | set CLASSPATH= 74 | 75 | 76 | @rem Execute Gradle 77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* 78 | 79 | :end 80 | @rem End local scope for the variables with windows NT shell 81 | if %ERRORLEVEL% equ 0 goto mainEnd 82 | 83 | :fail 84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 85 | rem the _cmd.exe /c_ return code! 86 | set EXIT_CODE=%ERRORLEVEL% 87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 89 | exit /b %EXIT_CODE% 90 | 91 | :mainEnd 92 | if "%OS%"=="Windows_NT" endlocal 93 | 94 | :omega 95 | -------------------------------------------------------------------------------- /release/changes.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gradle/android-cache-fix-gradle-plugin/3a5c46b0836b62ff4137914f91fce14a3907d22c/release/changes.md -------------------------------------------------------------------------------- /release/distribution/NOTICE: -------------------------------------------------------------------------------- 1 | The following copyright statements and licenses apply to various third party open 2 | source software packages (or portions thereof) that are distributed with 3 | this content. 4 | 5 | TABLE OF CONTENTS 6 | ================= 7 | 8 | The following is a listing of the open source components detailed in this 9 | document. This list is provided for your convenience; please read further if 10 | you wish to review the copyright notice(s) and the full text of the license 11 | associated with each component. 12 | 13 | 14 | **SECTION 1: Apache License, V2.0** 15 | * Google Guava 16 | * com.google.guava:guava 17 | 18 | SECTION 1: Apache License, V2.0 19 | =============================== 20 | 21 | Google Guava 22 | ------------ 23 | Copyright 2024 Google, Inc. 24 | 25 | Licensed under the Apache License, Version 2.0 (the "License"); 26 | you may not use this file except in compliance with the License. 27 | You may obtain a copy of the License at 28 | 29 | http://www.apache.org/licenses/LICENSE-2.0 30 | 31 | Unless required by applicable law or agreed to in writing, software 32 | distributed under the License is distributed on an "AS IS" BASIS, 33 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 34 | See the License for the specific language governing permissions and 35 | limitations under the License. 36 | -------------------------------------------------------------------------------- /release/version.txt: -------------------------------------------------------------------------------- 1 | 3.0.2 2 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.gradle.develocity") version "4.0.2" 3 | id("com.gradle.common-custom-user-data-gradle-plugin") version "2.3" 4 | id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" 5 | } 6 | 7 | val isCI = providers.environmentVariable("CI").isPresent 8 | 9 | develocity { 10 | server = "https://ge.solutions-team.gradle.com" 11 | buildScan { 12 | uploadInBackground = !isCI 13 | publishing.onlyIf { it.isAuthenticated } 14 | obfuscation { 15 | ipAddresses { addresses -> addresses.map { "0.0.0.0" } } 16 | } 17 | } 18 | } 19 | 20 | buildCache { 21 | local { 22 | isEnabled = true 23 | } 24 | 25 | remote(develocity.buildCache) { 26 | isEnabled = true 27 | val accessKey = System.getenv("GRADLE_ENTERPRISE_ACCESS_KEY") 28 | isPush = isCI && !accessKey.isNullOrEmpty() 29 | } 30 | } 31 | 32 | rootProject.name = "android-cache-fix-gradle-plugin" 33 | -------------------------------------------------------------------------------- /src/main/groovy/org/gradle/android/AndroidCacheFixPlugin.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android 2 | 3 | import com.google.common.collect.ImmutableList 4 | import groovy.transform.CompileStatic 5 | 6 | import org.gradle.android.workarounds.BundleLibraryClassesWorkaround 7 | 8 | import org.gradle.android.workarounds.CompileLibraryResourcesWorkaround 9 | import org.gradle.android.workarounds.DataBindingMergeDependencyArtifactsWorkaround 10 | import org.gradle.android.workarounds.JdkImageWorkaround 11 | import org.gradle.android.workarounds.LibraryJniLibsWorkaround 12 | import org.gradle.android.workarounds.MergeNativeLibsWorkaround 13 | 14 | import org.gradle.android.workarounds.MergeSourceSetFoldersWorkaround 15 | import org.gradle.android.workarounds.PackageForUnitTestWorkaround 16 | import org.gradle.android.workarounds.StripDebugSymbolsWorkaround 17 | import org.gradle.android.workarounds.Workaround 18 | import org.gradle.android.workarounds.ZipMergingTaskWorkaround 19 | import org.gradle.api.Plugin 20 | import org.gradle.api.Project 21 | import org.slf4j.Logger 22 | import org.slf4j.LoggerFactory 23 | 24 | import static org.gradle.android.Versions.* 25 | 26 | @CompileStatic 27 | class AndroidCacheFixPlugin implements Plugin { 28 | private static final Logger LOGGER = LoggerFactory.getLogger(AndroidCacheFixPlugin) 29 | 30 | private final List workarounds = [] as List 31 | 32 | static List initializeWorkarounds() { 33 | // This avoids trying to apply these workarounds to a build with a version of Android that does not contain 34 | // some of the classes the workarounds reference. In such a case, we can throw a friendlier "not supported" 35 | // error instead of a ClassDefNotFound. 36 | if (isSupportedAndroidVersion()) { 37 | return Arrays. asList( 38 | new MergeNativeLibsWorkaround(), 39 | new MergeSourceSetFoldersWorkaround(), 40 | new CompileLibraryResourcesWorkaround(), 41 | new StripDebugSymbolsWorkaround(), 42 | new BundleLibraryClassesWorkaround(), 43 | new DataBindingMergeDependencyArtifactsWorkaround(), 44 | new LibraryJniLibsWorkaround(), 45 | new ZipMergingTaskWorkaround(), 46 | new JdkImageWorkaround(), 47 | new PackageForUnitTestWorkaround(), 48 | ) 49 | } else { 50 | return Collections.emptyList() 51 | } 52 | } 53 | 54 | @Override 55 | void apply(Project project) { 56 | workarounds.addAll(initializeWorkarounds()) 57 | 58 | if (!isSupportedAndroidVersion()) { 59 | throw new RuntimeException("Android plugin ${CURRENT_ANDROID_VERSION} is not supported by Android cache fix plugin. For older Android Gradle Plugin versions, please use Android Cache Fix Plugin 2.4.6") 60 | } 61 | 62 | def appliedWorkarounds = [] 63 | getWorkaroundsToApply(CURRENT_ANDROID_VERSION, project, workarounds).each { Workaround workaround -> 64 | LOGGER.debug("Applying Android workaround {} to {}", workaround.getClass().simpleName, project) 65 | workaround.apply(project) 66 | appliedWorkarounds += workaround.getClass().simpleName - "Workaround" 67 | } 68 | 69 | project.gradle.sharedServices.registerIfAbsent("warnings", WarningsService.class) {}.get() 70 | } 71 | 72 | static List getWorkaroundsToApply( 73 | VersionNumber androidVersion, 74 | Project project, 75 | List workarounds 76 | ) { 77 | def workaroundsBuilder = ImmutableList. builder() 78 | for (def workaround : workarounds) { 79 | def androidIssue = workaround.class.getAnnotation(AndroidIssue) 80 | def introducedIn = android(androidIssue.introducedIn()) 81 | if (androidVersion < introducedIn) { 82 | continue 83 | } 84 | 85 | if (androidIssue.fixedIn().any { String fixedInVersionString -> 86 | def fixedInVersion = android(fixedInVersionString) 87 | androidVersion.baseVersion == fixedInVersion.baseVersion || androidVersion >= fixedInVersion 88 | }) { 89 | continue 90 | } 91 | 92 | if (project != null) { 93 | if (!workaround.canBeApplied(project)) { 94 | continue 95 | } 96 | } 97 | 98 | workaroundsBuilder.add(workaround) 99 | } 100 | workaroundsBuilder.build() 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/groovy/org/gradle/android/AndroidIssue.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android 2 | 3 | import java.lang.annotation.Documented 4 | import java.lang.annotation.ElementType 5 | import java.lang.annotation.Retention 6 | import java.lang.annotation.RetentionPolicy 7 | import java.lang.annotation.Target 8 | 9 | /** 10 | * Version of Android plugin that fixes the problem. Workaround not applied if current Android plugin version is the same or later. 11 | */ 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Documented 14 | @Target(ElementType.TYPE) 15 | @interface AndroidIssue { 16 | String introducedIn() 17 | String[] fixedIn() default [] 18 | String link() 19 | } 20 | -------------------------------------------------------------------------------- /src/main/groovy/org/gradle/android/Versions.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android 2 | 3 | import com.android.Version 4 | import groovy.transform.CompileStatic 5 | import groovy.transform.TypeCheckingMode 6 | import org.gradle.util.GradleVersion 7 | 8 | @CompileStatic(TypeCheckingMode.SKIP) 9 | class Versions { 10 | static final VersionNumber CURRENT_ANDROID_VERSION = android(Version.ANDROID_GRADLE_PLUGIN_VERSION) 11 | static final VersionNumber MINIMUM_ANDROID_VERSION = android("7.0.0-alpha01") 12 | 13 | static VersionNumber android(String version) { 14 | VersionNumber.parse(version) 15 | } 16 | 17 | static GradleVersion gradle(String version) { 18 | GradleVersion.version(version) 19 | } 20 | 21 | static boolean isSupportedAndroidVersion() { 22 | return CURRENT_ANDROID_VERSION >= MINIMUM_ANDROID_VERSION 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/groovy/org/gradle/android/Warnings.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android 2 | 3 | import groovy.transform.CompileStatic 4 | import org.gradle.android.workarounds.CompileLibraryResourcesWorkaround 5 | import org.gradle.api.Project 6 | 7 | import java.util.concurrent.atomic.AtomicBoolean 8 | 9 | @CompileStatic 10 | enum Warnings { 11 | USE_COMPILE_LIBRARY_RESOURCES_EXPERIMENTAL("WARNING: Android plugin ${Versions.CURRENT_ANDROID_VERSION} has experimental support for using relative path sensitivity with CompileLibraryResourcesTask inputs which will provide more build cache hits and improve build speed. Set '${CompileLibraryResourcesWorkaround.CACHE_COMPILE_LIB_RESOURCES}=true' and '${CompileLibraryResourcesWorkaround.ENABLE_SOURCE_SET_PATHS_MAP}=true' in gradle.properties to enable this support.") 12 | 13 | final String warning 14 | private final AtomicBoolean warned = new AtomicBoolean() 15 | 16 | Warnings(String warning) { 17 | this.warning = warning 18 | } 19 | 20 | void warnOnce(Project project) { 21 | if (isNotKotlinDslAccessors(project) && !warned.getAndSet(true)) { 22 | project.logger.warn(warning) 23 | } 24 | } 25 | 26 | void reset() { 27 | warned.set(false) 28 | } 29 | 30 | static void resetAll() { 31 | values().each {it.reset() } 32 | } 33 | 34 | static boolean isNotKotlinDslAccessors(Project project) { 35 | return project.rootProject.name != "gradle-kotlin-dsl-accessors" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/groovy/org/gradle/android/WarningsService.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android 2 | 3 | import groovy.transform.CompileStatic 4 | import org.gradle.api.services.BuildService 5 | import org.gradle.api.services.BuildServiceParameters 6 | 7 | @CompileStatic 8 | abstract class WarningsService implements BuildService, AutoCloseable { 9 | @Override 10 | void close() throws Exception { 11 | Warnings.resetAll() 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/groovy/org/gradle/android/workarounds/BundleLibraryClassesWorkaround.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android.workarounds 2 | 3 | import com.android.build.gradle.internal.tasks.BundleLibraryClassesDir 4 | import com.android.build.gradle.internal.tasks.BundleLibraryClassesJar 5 | import groovy.transform.CompileStatic 6 | import org.gradle.android.AndroidIssue 7 | import org.gradle.api.Project 8 | 9 | /** 10 | * Disables caching of the BundleLibraryClassesJar and BundleLibraryClassesDir tasks which are mostly disk bound and 11 | * unlikely to provide positive performance benefits. 12 | */ 13 | @AndroidIssue(introducedIn = "4.1.0", fixedIn = "7.2.0-alpha06", link = "https://issuetracker.google.com/issues/199763362") 14 | @CompileStatic 15 | class BundleLibraryClassesWorkaround implements Workaround { 16 | private static final String CACHING_ENABLED_PROPERTY = "org.gradle.android.cache-fix.BundleLibraryClasses.caching.enabled" 17 | 18 | @Override 19 | void apply(Project project) { 20 | project.tasks.withType(BundleLibraryClassesJar).configureEach { BundleLibraryClassesJar task -> 21 | task.outputs.doNotCacheIf("Caching BundleLibraryClassesJar is unlikely to provide positive performance results.", { true }) 22 | } 23 | project.tasks.withType(BundleLibraryClassesDir).configureEach { BundleLibraryClassesDir task -> 24 | task.outputs.doNotCacheIf("Caching BundleLibraryClassesDir is unlikely to provide positive performance results.", { true }) 25 | } 26 | } 27 | 28 | @Override 29 | boolean canBeApplied(Project project) { 30 | return !SystemPropertiesCompat.getBoolean(CACHING_ENABLED_PROPERTY, project) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/groovy/org/gradle/android/workarounds/CompileLibraryResourcesWorkaround.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android.workarounds 2 | 3 | import groovy.transform.CompileStatic 4 | import org.gradle.android.AndroidIssue 5 | import org.gradle.android.Warnings 6 | import org.gradle.api.Project 7 | 8 | /** 9 | * Warns if the user is not using experimental support for relative path sensitivity that was added 10 | * with 7.0.0-alpha09. 11 | */ 12 | @AndroidIssue(introducedIn = "7.0.0-alpha09", fixedIn = "7.2.0-beta01", link = "https://issuetracker.google.com/issues/155218379") 13 | @CompileStatic 14 | class CompileLibraryResourcesWorkaround implements Workaround { 15 | public static final String ENABLE_SOURCE_SET_PATHS_MAP = "android.experimental.enableSourceSetPathsMap" 16 | public static final String CACHE_COMPILE_LIB_RESOURCES = "android.experimental.cacheCompileLibResources" 17 | 18 | @Override 19 | void apply(Project project) { 20 | boolean enableSourceSetPathsMap = Boolean.valueOf(project.findProperty(ENABLE_SOURCE_SET_PATHS_MAP) as String) 21 | boolean cacheCompileLibResources = Boolean.valueOf(project.findProperty(CACHE_COMPILE_LIB_RESOURCES) as String) 22 | 23 | if (!(enableSourceSetPathsMap && cacheCompileLibResources)) { 24 | Warnings.USE_COMPILE_LIBRARY_RESOURCES_EXPERIMENTAL.warnOnce(project) 25 | } 26 | } 27 | 28 | @Override 29 | boolean canBeApplied(Project project) { 30 | return true 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/groovy/org/gradle/android/workarounds/DataBindingMergeDependencyArtifactsWorkaround.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android.workarounds 2 | 3 | import com.android.build.gradle.internal.tasks.databinding.DataBindingMergeDependencyArtifactsTask 4 | import groovy.transform.CompileStatic 5 | import org.gradle.android.AndroidIssue 6 | import org.gradle.api.Project 7 | import org.gradle.api.Task 8 | 9 | /** 10 | * Disables caching of the DataBindingMergeDependencyArtifactsTask task which is mostly disk bound and 11 | * unlikely to provide positive performance benefits. 12 | */ 13 | @AndroidIssue(introducedIn = "3.5.0", fixedIn = "7.2.0-alpha06", link = "https://issuetracker.google.com/issues/200002454") 14 | @CompileStatic 15 | class DataBindingMergeDependencyArtifactsWorkaround implements Workaround { 16 | private static final String CACHING_ENABLED_PROPERTY = "org.gradle.android.cache-fix.DataBindingMergeDependencyArtifacts.caching.enabled" 17 | 18 | @Override 19 | void apply(Project project) { 20 | project.tasks.withType(DataBindingMergeDependencyArtifactsTask).configureEach { Task task -> 21 | task.outputs.doNotCacheIf("Caching DataBindingMergeDependencyArtifacts is unlikely to provide positive performance results.", { true }) 22 | } 23 | } 24 | 25 | @Override 26 | boolean canBeApplied(Project project) { 27 | return !SystemPropertiesCompat.getBoolean(CACHING_ENABLED_PROPERTY, project) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/groovy/org/gradle/android/workarounds/JdkImageWorkaround.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android.workarounds 2 | 3 | import com.google.common.annotations.VisibleForTesting 4 | import com.google.common.collect.Lists 5 | import org.gradle.android.AndroidIssue 6 | import org.gradle.android.Versions 7 | import org.gradle.api.Project 8 | import org.gradle.api.artifacts.transform.CacheableTransform 9 | import org.gradle.api.artifacts.transform.InputArtifact 10 | import org.gradle.api.artifacts.transform.TransformAction 11 | import org.gradle.api.artifacts.transform.TransformOutputs 12 | import org.gradle.api.artifacts.transform.TransformParameters 13 | import org.gradle.api.attributes.Attribute 14 | import org.gradle.api.file.Directory 15 | import org.gradle.api.file.FileCollection 16 | import org.gradle.api.file.FileSystemLocation 17 | import org.gradle.api.file.FileSystemOperations 18 | import org.gradle.api.internal.artifacts.ArtifactAttributes 19 | import org.gradle.api.provider.Provider 20 | import org.gradle.api.tasks.Classpath 21 | import org.gradle.api.tasks.Internal 22 | import org.gradle.api.tasks.compile.JavaCompile 23 | import org.gradle.process.CommandLineArgumentProvider 24 | import org.gradle.process.ExecOperations 25 | 26 | import javax.inject.Inject 27 | import java.lang.module.ModuleDescriptor 28 | import java.nio.ByteBuffer 29 | import java.nio.file.Files 30 | import java.util.stream.Collectors 31 | import java.util.stream.Stream 32 | 33 | /** 34 | * Works around cache misses due to the custom Java runtime used when source compatibility is set higher 35 | * than Java 9. This normalizes out minor inconsequential differences between JDKs used to generate the 36 | * custom runtime and improve cache hits between environments. 37 | */ 38 | @AndroidIssue(introducedIn = "7.1.0", link = "https://issuetracker.google.com/u/1/issues/234820480") 39 | class JdkImageWorkaround implements Workaround { 40 | static final String WORKAROUND_ENABLED_PROPERTY = "org.gradle.android.cache-fix.JdkImageWorkaround.enabled" 41 | 42 | static final String JDK_IMAGE = "_internal_android_jdk_image" 43 | static final String JDK_IMAGE_EXTRACTED = "_internal_android_jdk_image_extracted" 44 | static final String JDK_IMAGE_CONFIG_NAME = "androidJdkImage" 45 | 46 | @Override 47 | void apply(Project project) { 48 | // We would prefer not to configure this if a jdkImage is not in use, but the attributes 49 | // being ignored are unlikely to ever have a runtime impact. Doing this outside of task 50 | // configuration prevents issues with things that use the tooling api to finalize the 51 | // runtime configuration before querying (and instantiating) task configurations. 52 | applyRuntimeClasspathNormalization(project) 53 | 54 | applyToAllAndroidVariants(project) { variant -> 55 | variant.javaCompileProvider.configure { JavaCompile task -> 56 | def jdkImageInput = getJdkImageInput(task) 57 | if (jdkImageInput != null) { 58 | setupExtractedJdkImageInputTransform(project, getJvmHome(task)) 59 | replaceCommandLineProvider(task, jdkImageInput) 60 | } 61 | } 62 | } 63 | } 64 | 65 | // Configuration for Old Variant API will drop in AGP 9. We will need to use a different 66 | // approach to retrieve the variants using the new Variant API. 67 | private static void applyToAllAndroidVariants(Project project, Closure configureVariant) { 68 | project.plugins.withId("com.android.application") { 69 | def android = project.extensions.findByName("android") 70 | android.unitTestVariants.all(configureVariant) 71 | android.applicationVariants.all(configureVariant) 72 | } 73 | 74 | project.plugins.withId("com.android.library") { 75 | def android = project.extensions.findByName("android") 76 | android.unitTestVariants.all(configureVariant) 77 | android.libraryVariants.all(configureVariant) 78 | } 79 | } 80 | 81 | static def applyRuntimeClasspathNormalization(Project project) { 82 | project.normalization { handler -> 83 | handler.runtimeClasspath { 84 | it.metaInf { metaInfNormalization -> 85 | metaInfNormalization.ignoreAttribute('Implementation-Version') 86 | metaInfNormalization.ignoreAttribute('Implementation-Vendor') 87 | metaInfNormalization.ignoreAttribute('Created-By') 88 | } 89 | } 90 | } 91 | } 92 | 93 | static def getJdkImageInput(JavaCompile task) { 94 | return task.options.compilerArgumentProviders.find { it.class.simpleName == "JdkImageInput" } 95 | } 96 | 97 | static void setupExtractedJdkImageInputTransform(Project project, Provider javaHome) { 98 | project.dependencies.registerTransform(ExtractJdkImageTransform) {spec -> 99 | spec.from.attribute(ArtifactAttributes.ARTIFACT_FORMAT, JDK_IMAGE) 100 | spec.to.attribute(ArtifactAttributes.ARTIFACT_FORMAT, JDK_IMAGE_EXTRACTED) 101 | spec.parameters.javaHome = javaHome 102 | } 103 | } 104 | 105 | static void replaceCommandLineProvider(JavaCompile task, jdkImageInput) { 106 | Attribute jdkId = Attribute.of("jdk-id", String) 107 | def jdkConfiguration = task.project.configurations.getByName(JDK_IMAGE_CONFIG_NAME) 108 | def extractedJdkImage = jdkConfiguration.incoming.artifactView {viewConfiguration -> 109 | viewConfiguration.attributes { 110 | it.attribute(ArtifactAttributes.ARTIFACT_FORMAT, JDK_IMAGE_EXTRACTED) 111 | it.attribute(jdkId, getJvmVersion(task) + getJvmVendor(task)) 112 | } 113 | }.artifacts.artifactFiles 114 | def extractedJdkImageProvider = new ExtractedJdkImageCommandLineProvider(extractedJdkImage, jdkImageInput.jdkImage) 115 | task.options.compilerArgumentProviders.remove(jdkImageInput) 116 | task.options.compilerArgumentProviders.add(extractedJdkImageProvider) 117 | } 118 | 119 | static String getJvmVersion(JavaCompile task) { 120 | return task.javaCompiler.map { it.metadata.jvmVersion } 121 | .orElse(SystemPropertiesCompat.getString("java.version", task.project, null)) 122 | } 123 | 124 | static String getJvmVendor(JavaCompile task) { 125 | return task.javaCompiler.map { it.metadata.vendor } 126 | .orElse(SystemPropertiesCompat.getString("java.vendor", task.project, null)) 127 | } 128 | 129 | static Provider getJvmHome(JavaCompile task) { 130 | def defaultJvmHome = task.project.objects.directoryProperty() 131 | defaultJvmHome.set(new File(SystemPropertiesCompat.getString("java.home", task.project, null))) 132 | return task.javaCompiler.map { it.metadata.installationPath } 133 | .orElse(defaultJvmHome) 134 | } 135 | 136 | @Override 137 | boolean canBeApplied(Project project) { 138 | return SystemPropertiesCompat.getBoolean(WORKAROUND_ENABLED_PROPERTY, project, true) 139 | } 140 | 141 | static class ExtractedJdkImageCommandLineProvider implements CommandLineArgumentProvider { 142 | @Classpath 143 | final FileCollection extractedJdkImage 144 | 145 | @Internal 146 | final FileCollection jdkImage 147 | 148 | ExtractedJdkImageCommandLineProvider(FileCollection extractedJdkImage, FileCollection jdkImage) { 149 | this.extractedJdkImage = extractedJdkImage 150 | this.jdkImage = jdkImage 151 | } 152 | 153 | @Override 154 | Iterable asArguments() { 155 | return ["--system", new File(jdkImage.singleFile, "jdkImage").absolutePath] 156 | } 157 | } 158 | 159 | @CacheableTransform 160 | abstract static class ExtractJdkImageTransform implements TransformAction { 161 | interface Parameters extends TransformParameters { 162 | @Internal 163 | Provider getJavaHome() 164 | 165 | void setJavaHome(Provider javaHome) 166 | } 167 | 168 | @Inject 169 | abstract ExecOperations getExecOperations() 170 | 171 | @Inject 172 | abstract FileSystemOperations getFileOperations() 173 | 174 | @Classpath 175 | @InputArtifact 176 | abstract Provider getJdkImageDir() 177 | 178 | @Override 179 | void transform(TransformOutputs outputs) { 180 | // Extract the contents of the runtime jimage file 181 | def targetDir = outputs.dir("extracted") 182 | execOperations.exec { 183 | executable = new File(parameters.javaHome.get().asFile, "bin/jimage") 184 | args( 185 | "extract", 186 | "--dir", 187 | targetDir, 188 | new File(jdkImageDir.get().asFile, "jdkImage/lib/modules").absolutePath 189 | ) 190 | } 191 | 192 | // Starting with AGP 8 only the major Java version is stored in the output so we don't need any normalization 193 | if (Versions.CURRENT_ANDROID_VERSION.major < 8) { 194 | // Capture the module descriptor ignoring the version, which is not enforced anyways 195 | File moduleInfoFile = new File(targetDir, 'java.base/module-info.class') 196 | ModuleDescriptor descriptor = captureModuleDescriptorWithoutVersion(moduleInfoFile) 197 | File descriptorData = new File(targetDir, "module-descriptor.txt") 198 | descriptorData.text = serializeDescriptor(descriptor) 199 | fileOperations.delete { 200 | delete(moduleInfoFile) 201 | } 202 | } 203 | } 204 | 205 | private static ModuleDescriptor captureModuleDescriptorWithoutVersion(File moduleFile) { 206 | return ModuleDescriptor.read(ByteBuffer.wrap(Files.readAllBytes(moduleFile.toPath()))) 207 | } 208 | 209 | @VisibleForTesting 210 | static String serializeDescriptor(ModuleDescriptor descriptor) { 211 | StringBuilder sb = new StringBuilder() 212 | 213 | if (descriptor.isOpen()) { 214 | sb.append("open ") 215 | } 216 | sb.append("module { name: ").append(descriptor.name()) 217 | if (!descriptor.requires().isEmpty()) { 218 | sb.append(", ").append(descriptor.requires().sort().collect { serializeRequires(it) }) 219 | } 220 | if (!descriptor.uses().isEmpty()) { 221 | sb.append(", uses: ").append(descriptor.uses().sort()) 222 | } 223 | if (!descriptor.exports().isEmpty()) { 224 | sb.append(", exports: ").append(descriptor.exports().sort().collect { serializeExports(it) }) 225 | } 226 | if (!descriptor.opens().isEmpty()) { 227 | sb.append(", opens: ").append(descriptor.opens().sort().collect { serializeOpens(it) }) 228 | } 229 | if (!descriptor.provides().isEmpty()) { 230 | sb.append(", provides: ").append(descriptor.provides().sort().collect { serializeProvides(it) }) 231 | } 232 | sb.append(" }") 233 | return sb.toString() 234 | } 235 | 236 | private static String serializeRequires(ModuleDescriptor.Requires requires) { 237 | String requireString 238 | if (!requires.compiledVersion().empty) { 239 | requireString = requires.name() + " (@" + requires.compiledVersion() + ")" 240 | } else { 241 | requireString = requires.name() 242 | } 243 | return withSerializedMods(requires.modifiers(), requireString) 244 | } 245 | 246 | private static String serializeExports(ModuleDescriptor.Exports exports) { 247 | String s = withSerializedMods(exports.modifiers(), exports.source()) 248 | if (exports.targets().isEmpty()) { 249 | return s; 250 | } else { 251 | return s + " to " + exports.targets().sort() 252 | } 253 | } 254 | 255 | private static String serializeOpens(ModuleDescriptor.Opens opens) { 256 | String s = withSerializedMods(opens.modifiers(), opens.source()) 257 | if (opens.targets().isEmpty()) { 258 | return s; 259 | } else { 260 | return s + " to " + opens.targets().sort() 261 | } 262 | } 263 | 264 | private static String serializeProvides(ModuleDescriptor.Provides provides) { 265 | return provides.service() + " with " + Lists.newArrayList(provides.providers()).sort() 266 | } 267 | 268 | static String withSerializedMods(Set mods, String what) { 269 | return (Stream.concat(mods.stream().map(e -> e.toString() 270 | .toLowerCase(Locale.ROOT)).sorted(), 271 | Stream.of(what))) 272 | .collect(Collectors.joining(" ")) 273 | } 274 | } 275 | } 276 | -------------------------------------------------------------------------------- /src/main/groovy/org/gradle/android/workarounds/LibraryJniLibsWorkaround.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android.workarounds 2 | 3 | import com.android.build.gradle.internal.tasks.LibraryJniLibsTask; 4 | import groovy.transform.CompileStatic; 5 | import org.gradle.android.AndroidIssue; 6 | import org.gradle.api.Project 7 | import org.gradle.api.Task; 8 | 9 | /** 10 | * Disables caching of the LibraryJniLibsTask task which is mostly disk bound and 11 | * unlikely to provide positive performance benefits. 12 | */ 13 | @AndroidIssue(introducedIn = "3.6.0", fixedIn = "7.2.0-alpha06", link = "https://issuetracker.google.com/issues/200002454") 14 | @CompileStatic 15 | class LibraryJniLibsWorkaround implements Workaround { 16 | 17 | private static final String CACHING_ENABLED_PROPERTY = "org.gradle.android.cache-fix.LibraryJniLibs.caching.enabled" 18 | 19 | @Override 20 | void apply(Project project) { 21 | project.tasks.withType(LibraryJniLibsTask).configureEach { Task task -> 22 | task.outputs.doNotCacheIf("Caching LibraryJniLibs is unlikely to provide positive performance results.", { true }) 23 | } 24 | } 25 | 26 | @Override 27 | boolean canBeApplied(Project project) { 28 | return !SystemPropertiesCompat.getBoolean(CACHING_ENABLED_PROPERTY, project) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/groovy/org/gradle/android/workarounds/MergeNativeLibsWorkaround.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android.workarounds 2 | 3 | import com.android.build.gradle.internal.tasks.MergeNativeLibsTask 4 | import groovy.transform.CompileStatic 5 | import org.gradle.android.AndroidIssue 6 | import org.gradle.api.Project 7 | import org.gradle.api.Task 8 | 9 | @AndroidIssue(introducedIn = "3.5.0", fixedIn = "7.2.0-alpha06", link = "https://issuetracker.google.com/issues/153088766") 10 | @CompileStatic 11 | class MergeNativeLibsWorkaround implements Workaround { 12 | private static final String CACHING_ENABLED_PROPERTY = "org.gradle.android.cache-fix.MergeNativeLibs.caching.enabled" 13 | 14 | @Override 15 | void apply(Project project) { 16 | project.tasks.withType(MergeNativeLibsTask).configureEach { Task task -> 17 | task.outputs.doNotCacheIf("Caching MergeNativeLibs is unlikely to provide positive performance results.", {true }) 18 | } 19 | } 20 | 21 | @Override 22 | boolean canBeApplied(Project project) { 23 | return !SystemPropertiesCompat.getBoolean(CACHING_ENABLED_PROPERTY, project) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/groovy/org/gradle/android/workarounds/MergeSourceSetFoldersWorkaround.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android.workarounds 2 | 3 | import com.android.build.gradle.tasks.MergeSourceSetFolders 4 | import groovy.transform.CompileStatic 5 | import org.gradle.android.AndroidIssue 6 | import org.gradle.api.Project 7 | import org.gradle.api.Task 8 | 9 | /** 10 | * Disables caching of the MergeSourceSetFolders task which is mostly disk bound and unlikely to provide positive 11 | * performance benefits. 12 | */ 13 | @CompileStatic 14 | @AndroidIssue(introducedIn = "3.5.0", fixedIn = ["8.4.0-alpha01"], link = "https://issuetracker.google.com/issues/194804421") 15 | class MergeSourceSetFoldersWorkaround implements Workaround { 16 | private static final String CACHING_ENABLED_PROPERTY = "org.gradle.android.cache-fix.MergeSourceSetFolders.caching.enabled" 17 | 18 | @Override 19 | void apply(Project project) { 20 | project.tasks.withType(MergeSourceSetFolders).configureEach { Task task -> 21 | task.outputs.doNotCacheIf("Caching MergeSourceSetFolders is unlikely to provide positive performance results.", { true }) 22 | } 23 | } 24 | 25 | @Override 26 | boolean canBeApplied(Project project) { 27 | return !SystemPropertiesCompat.getBoolean(CACHING_ENABLED_PROPERTY, project) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/groovy/org/gradle/android/workarounds/PackageForUnitTestWorkaround.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android.workarounds 2 | 3 | import com.android.build.gradle.internal.tasks.PackageForUnitTest 4 | import groovy.transform.CompileStatic 5 | import org.gradle.android.AndroidIssue 6 | import org.gradle.api.Project 7 | import org.gradle.api.Task 8 | 9 | @AndroidIssue(introducedIn = "3.5.0-alpha05", fixedIn = "8.3.0-alpha01", link = "https://issuetracker.google.com/issues/292114808") 10 | @CompileStatic 11 | class PackageForUnitTestWorkaround implements Workaround { 12 | private static final String CACHING_ENABLED_PROPERTY = "org.gradle.android.cache-fix.PackageForUnitTest.caching.enabled" 13 | 14 | @Override 15 | void apply(Project project) { 16 | project.tasks.withType(PackageForUnitTest).configureEach { Task task -> 17 | task.outputs.doNotCacheIf("Caching PackageForUnitTest is unlikely to provide positive performance results.", { true }) 18 | } 19 | } 20 | 21 | @Override 22 | boolean canBeApplied(Project project) { 23 | return !SystemPropertiesCompat.getBoolean(CACHING_ENABLED_PROPERTY, project) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/groovy/org/gradle/android/workarounds/StripDebugSymbolsWorkaround.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android.workarounds 2 | 3 | import com.android.build.gradle.internal.tasks.StripDebugSymbolsTask 4 | import groovy.transform.CompileStatic 5 | import org.gradle.android.AndroidIssue 6 | import org.gradle.api.Project 7 | import org.gradle.api.Task 8 | 9 | /** 10 | * Disables caching of the StripDebugSymbols task which is mostly disk bound and unlikely to provide positive 11 | * performance benefits. 12 | */ 13 | @AndroidIssue(introducedIn = "3.5.0", fixedIn = "7.2.0-alpha06", link = "https://issuetracker.google.com/issues/181143775") 14 | @CompileStatic 15 | class StripDebugSymbolsWorkaround implements Workaround { 16 | private static final String CACHING_ENABLED_PROPERTY = "org.gradle.android.cache-fix.StripDebugSymbols.caching.enabled" 17 | 18 | @Override 19 | void apply(Project project) { 20 | project.tasks.withType(StripDebugSymbolsTask).configureEach { Task task -> 21 | task.outputs.doNotCacheIf("Caching StripDebugSymbolsTask is unlikely to provide positive performance results.", { true }) 22 | } 23 | } 24 | 25 | @Override 26 | boolean canBeApplied(Project project) { 27 | return !SystemPropertiesCompat.getBoolean(CACHING_ENABLED_PROPERTY, project) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/groovy/org/gradle/android/workarounds/SystemPropertiesCompat.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android.workarounds 2 | 3 | import groovy.transform.CompileStatic 4 | import org.gradle.android.Versions 5 | import org.gradle.api.Project 6 | import org.gradle.api.provider.Provider 7 | import org.gradle.util.GradleVersion 8 | 9 | @CompileStatic 10 | class SystemPropertiesCompat { 11 | 12 | /** 13 | * Backward-compatible boolean system property check. This allows use of new ProviderFactory methods 14 | * on newer Gradle versions while falling back to old APIs gracefully on older APIs. 15 | * 16 | * @param key the key to look up. 17 | * @param project the source gradle project. May be null. 18 | * @return the system property value or false if absent. 19 | */ 20 | static boolean getBoolean(String key, Project project) { 21 | return getBoolean(key, project, false) 22 | } 23 | 24 | /** 25 | * Backward-compatible boolean system property check. This allows use of new ProviderFactory methods 26 | * on newer Gradle versions while falling back to old APIs gracefully on older APIs. 27 | * 28 | * @param key the key to look up. 29 | * @param project the source gradle project. May be null. 30 | * @param the default value to return if the value is absent 31 | * @return the system property value or default value if absent. 32 | */ 33 | static boolean getBoolean(String key, Project project, Boolean absentValue) { 34 | if (project != null) { 35 | getSystemProperty(key, project).map { 36 | try { 37 | return Boolean.parseBoolean(it) 38 | } catch (IllegalArgumentException | NullPointerException ignored) { 39 | return absentValue 40 | } 41 | } 42 | .getOrElse(absentValue) 43 | } else { 44 | return Boolean.getBoolean(key) 45 | } 46 | } 47 | 48 | static String getString(String key, Project project, String absentValue) { 49 | if (project != null) { 50 | getSystemProperty(key, project).getOrElse(absentValue) 51 | } else { 52 | return System.getProperty(key) 53 | } 54 | } 55 | 56 | private static Provider getSystemProperty(String key, Project project) { 57 | def systemProperty = project.providers.systemProperty(key) 58 | 59 | if (Versions.gradle(project.gradle.gradleVersion) < GradleVersion.version("7.4")) { 60 | systemProperty = systemProperty.forUseAtConfigurationTime() 61 | } 62 | 63 | return systemProperty 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/groovy/org/gradle/android/workarounds/Workaround.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android.workarounds 2 | 3 | import groovy.transform.CompileStatic 4 | import org.gradle.api.Project 5 | 6 | /** 7 | * Workaround to apply to an Android project. Can be annotated with {@literal @}{@link org.gradle.android.AndroidIssue}. 8 | */ 9 | @CompileStatic 10 | interface Workaround { 11 | void apply(Project project) 12 | boolean canBeApplied(Project project) 13 | } 14 | -------------------------------------------------------------------------------- /src/main/groovy/org/gradle/android/workarounds/ZipMergingTaskWorkaround.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android.workarounds 2 | 3 | import com.android.build.gradle.tasks.ZipMergingTask 4 | import groovy.transform.CompileStatic 5 | import org.gradle.android.AndroidIssue 6 | import org.gradle.api.Project 7 | import org.gradle.api.Task 8 | 9 | /** 10 | * Disables caching of ZipMergingTask which is mostly disk bound and 11 | * unlikely to provide positive performance benefits. 12 | */ 13 | @AndroidIssue(introducedIn = "3.5.0", fixedIn = "8.1.0-alpha10", link="https://issuetracker.google.com/issues/200002454") 14 | @CompileStatic 15 | class ZipMergingTaskWorkaround implements Workaround { 16 | 17 | private static final String CACHING_ENABLED_PROPERTY = "org.gradle.android.cache-fix.ZipMergingTask.caching.enabled" 18 | 19 | @Override 20 | void apply(Project project) { 21 | project.tasks.withType(ZipMergingTask).configureEach { Task task -> 22 | task.outputs.doNotCacheIf("Caching ZipMergingTask is unlikely to provide positive performance results.", { true }) 23 | } 24 | } 25 | 26 | @Override 27 | boolean canBeApplied(Project project) { 28 | return !SystemPropertiesCompat.getBoolean(CACHING_ENABLED_PROPERTY, project) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/gradle/android/VersionNumber.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradle.android; 18 | 19 | import com.google.common.base.Objects; 20 | import com.google.common.collect.Ordering; 21 | 22 | import javax.annotation.Nullable; 23 | 24 | /** 25 | * Represents, parses, and compares version numbers. Supports a couple of different schemes:
  • MAJOR.MINOR.MICRO-QUALIFIER (the default).
  • MAJOR.MINOR.MICRO.PATCH-QUALIFIER.
26 | * 27 | *

The {@link #parse} method handles missing parts and allows "." to be used instead of "-", and "_" to be used instead of "." for the patch number. 28 | * 29 | *

This class considers missing parts to be 0, so that "1.0" == "1.0.0" == "1.0.0_0".

30 | * 31 | *

Note that this class considers "1.2.3-something" less than "1.2.3". Qualifiers are compared lexicographically ("1.2.3-alpha" < "1.2.3-beta") and case-insensitive ("1.2.3-alpha" < 32 | * "1.2.3.RELEASE"). 33 | * 34 | *

To check if a version number is at least "1.2.3", disregarding a potential qualifier like "beta", use {@code version.getBaseVersion().compareTo(VersionNumber.parse("1.2.3")) >= 0}. 35 | * 36 | *

This implementation is copied from Gradle 7.4.2, as this class was originally part of the {@code org.gradle.util} package, but was deprecated. 37 | */ 38 | public class VersionNumber implements Comparable { 39 | private static final DefaultScheme DEFAULT_SCHEME = new DefaultScheme(); 40 | private static final SchemeWithPatchVersion PATCH_SCHEME = new SchemeWithPatchVersion(); 41 | public static final VersionNumber UNKNOWN = version(0); 42 | 43 | private final int major; 44 | private final int minor; 45 | private final int micro; 46 | private final int patch; 47 | private final String qualifier; 48 | private final AbstractScheme scheme; 49 | 50 | public VersionNumber(int major, int minor, int micro, @Nullable String qualifier) { 51 | this(major, minor, micro, 0, qualifier, DEFAULT_SCHEME); 52 | } 53 | 54 | public VersionNumber(int major, int minor, int micro, int patch, @Nullable String qualifier) { 55 | this(major, minor, micro, patch, qualifier, PATCH_SCHEME); 56 | } 57 | 58 | private VersionNumber(int major, int minor, int micro, int patch, @Nullable String qualifier, AbstractScheme scheme) { 59 | this.major = major; 60 | this.minor = minor; 61 | this.micro = micro; 62 | this.patch = patch; 63 | this.qualifier = qualifier; 64 | this.scheme = scheme; 65 | } 66 | 67 | public int getMajor() { 68 | return major; 69 | } 70 | 71 | public int getMinor() { 72 | return minor; 73 | } 74 | 75 | public int getMicro() { 76 | return micro; 77 | } 78 | 79 | public int getPatch() { 80 | return patch; 81 | } 82 | 83 | @Nullable 84 | public String getQualifier() { 85 | return qualifier; 86 | } 87 | 88 | public VersionNumber getBaseVersion() { 89 | return new VersionNumber(major, minor, micro, patch, null, scheme); 90 | } 91 | 92 | @Override 93 | public int compareTo(VersionNumber other) { 94 | if (major != other.major) { 95 | return major - other.major; 96 | } 97 | if (minor != other.minor) { 98 | return minor - other.minor; 99 | } 100 | if (micro != other.micro) { 101 | return micro - other.micro; 102 | } 103 | if (patch != other.patch) { 104 | return patch - other.patch; 105 | } 106 | return Ordering.natural().nullsLast().compare(toLowerCase(qualifier), toLowerCase(other.qualifier)); 107 | } 108 | 109 | @Override 110 | public boolean equals(@Nullable Object other) { 111 | return other instanceof VersionNumber && compareTo((VersionNumber) other) == 0; 112 | } 113 | 114 | @Override 115 | public int hashCode() { 116 | int result = major; 117 | result = 31 * result + minor; 118 | result = 31 * result + micro; 119 | result = 31 * result + patch; 120 | result = 31 * result + Objects.hashCode(qualifier); 121 | return result; 122 | } 123 | 124 | @Override 125 | public String toString() { 126 | return scheme.format(this); 127 | } 128 | 129 | public static VersionNumber version(int major) { 130 | return version(major, 0); 131 | } 132 | 133 | public static VersionNumber version(int major, int minor) { 134 | return new VersionNumber(major, minor, 0, 0, null, DEFAULT_SCHEME); 135 | } 136 | 137 | /** 138 | * Returns the default MAJOR.MINOR.MICRO-QUALIFIER scheme. 139 | */ 140 | public static Scheme scheme() { 141 | return DEFAULT_SCHEME; 142 | } 143 | 144 | /** 145 | * Returns the MAJOR.MINOR.MICRO.PATCH-QUALIFIER scheme. 146 | */ 147 | public static Scheme withPatchNumber() { 148 | return PATCH_SCHEME; 149 | } 150 | 151 | public static VersionNumber parse(String versionString) { 152 | return DEFAULT_SCHEME.parse(versionString); 153 | } 154 | 155 | @Nullable 156 | private String toLowerCase(@Nullable String string) { 157 | return string == null ? null : string.toLowerCase(); 158 | } 159 | 160 | /** 161 | * Returns the version number scheme. 162 | */ 163 | public interface Scheme { 164 | VersionNumber parse(String value); 165 | 166 | String format(VersionNumber versionNumber); 167 | } 168 | 169 | private abstract static class AbstractScheme implements Scheme { 170 | final int depth; 171 | 172 | protected AbstractScheme(int depth) { 173 | this.depth = depth; 174 | } 175 | 176 | @Override 177 | public VersionNumber parse(@Nullable String versionString) { 178 | if (versionString == null || versionString.length() == 0) { 179 | return UNKNOWN; 180 | } 181 | Scanner scanner = new Scanner(versionString); 182 | 183 | int major = 0; 184 | int minor = 0; 185 | int micro = 0; 186 | int patch = 0; 187 | 188 | if (!scanner.hasDigit()) { 189 | return UNKNOWN; 190 | } 191 | major = scanner.scanDigit(); 192 | if (scanner.isSeparatorAndDigit('.')) { 193 | scanner.skipSeparator(); 194 | minor = scanner.scanDigit(); 195 | if (scanner.isSeparatorAndDigit('.')) { 196 | scanner.skipSeparator(); 197 | micro = scanner.scanDigit(); 198 | if (depth > 3 && scanner.isSeparatorAndDigit('.', '_')) { 199 | scanner.skipSeparator(); 200 | patch = scanner.scanDigit(); 201 | } 202 | } 203 | } 204 | 205 | if (scanner.isEnd()) { 206 | return new VersionNumber(major, minor, micro, patch, null, this); 207 | } 208 | 209 | if (scanner.isQualifier()) { 210 | scanner.skipSeparator(); 211 | return new VersionNumber(major, minor, micro, patch, scanner.remainder(), this); 212 | } 213 | 214 | return UNKNOWN; 215 | } 216 | 217 | private static class Scanner { 218 | int pos; 219 | final String str; 220 | 221 | private Scanner(String string) { 222 | this.str = string; 223 | } 224 | 225 | boolean hasDigit() { 226 | return pos < str.length() && Character.isDigit(str.charAt(pos)); 227 | } 228 | 229 | boolean isSeparatorAndDigit(char... separators) { 230 | return pos < str.length() - 1 && oneOf(separators) && Character.isDigit(str.charAt(pos + 1)); 231 | } 232 | 233 | private boolean oneOf(char... separators) { 234 | char current = str.charAt(pos); 235 | for (int i = 0; i < separators.length; i++) { 236 | char separator = separators[i]; 237 | if (current == separator) { 238 | return true; 239 | } 240 | } 241 | return false; 242 | } 243 | 244 | boolean isQualifier() { 245 | return pos < str.length() - 1 && oneOf('.', '-'); 246 | } 247 | 248 | int scanDigit() { 249 | int start = pos; 250 | while (hasDigit()) { 251 | pos++; 252 | } 253 | return Integer.parseInt(str.substring(start, pos)); 254 | } 255 | 256 | public boolean isEnd() { 257 | return pos == str.length(); 258 | } 259 | 260 | public void skipSeparator() { 261 | pos++; 262 | } 263 | 264 | @Nullable 265 | public String remainder() { 266 | return pos == str.length() ? null : str.substring(pos); 267 | } 268 | } 269 | } 270 | 271 | private static class DefaultScheme extends AbstractScheme { 272 | private static final String VERSION_TEMPLATE = "%d.%d.%d%s"; 273 | 274 | public DefaultScheme() { 275 | super(3); 276 | } 277 | 278 | @Override 279 | public String format(VersionNumber versionNumber) { 280 | return String.format(VERSION_TEMPLATE, versionNumber.major, versionNumber.minor, versionNumber.micro, versionNumber.qualifier == null ? "" : "-" + versionNumber.qualifier); 281 | } 282 | } 283 | 284 | private static class SchemeWithPatchVersion extends AbstractScheme { 285 | private static final String VERSION_TEMPLATE = "%d.%d.%d.%d%s"; 286 | 287 | private SchemeWithPatchVersion() { 288 | super(4); 289 | } 290 | 291 | @Override 292 | public String format(VersionNumber versionNumber) { 293 | return String.format(VERSION_TEMPLATE, versionNumber.major, versionNumber.minor, versionNumber.micro, versionNumber.patch, versionNumber.qualifier == null ? "" : "-" + versionNumber.qualifier); 294 | } 295 | } 296 | 297 | } 298 | 299 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradle/android/AbstractTest.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android 2 | 3 | import org.gradle.testkit.runner.GradleRunner 4 | import org.junit.Rule 5 | import org.junit.rules.TemporaryFolder 6 | import spock.lang.Specification 7 | 8 | class AbstractTest extends Specification { 9 | @Rule TemporaryFolder temporaryFolder 10 | File cacheDir 11 | 12 | def setup() { 13 | cacheDir = temporaryFolder.newFolder() 14 | } 15 | 16 | def withGradleVersion(String gradleVersion) { 17 | GradleRunner.create() 18 | .withGradleVersion(gradleVersion) 19 | .forwardOutput() 20 | .withDebug(false) 21 | } 22 | 23 | File file(String path) { 24 | return new File(temporaryFolder.root, path) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradle/android/CodeSnippets.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android 2 | 3 | class CodeSnippets { 4 | 5 | static String getJavaActivity(String packageName, String resourceName) { 6 | return """ 7 | package ${packageName}; 8 | 9 | import org.joda.time.LocalTime; 10 | 11 | import android.app.Activity; 12 | import android.os.Bundle; 13 | import android.widget.TextView; 14 | 15 | public class HelloActivity extends Activity { 16 | 17 | @Override 18 | public void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.${resourceName}_layout); 21 | } 22 | 23 | @Override 24 | public void onStart() { 25 | super.onStart(); 26 | LocalTime currentTime = new LocalTime(); 27 | TextView textView = (TextView) findViewById(R.id.text_view); 28 | textView.setText("The current local time is: " + currentTime); 29 | } 30 | } 31 | """.stripIndent() 32 | } 33 | 34 | static String getJavaAndroidTest(String packageName) { 35 | return """ 36 | package ${packageName}; 37 | 38 | public class JavaUserAndroidTest { 39 | } 40 | """.stripIndent() 41 | } 42 | 43 | static String getJavaSimpleTest(String packageName) { 44 | return """ 45 | package ${packageName}; 46 | 47 | public class JavaUserTest { 48 | } 49 | """.stripIndent() 50 | } 51 | 52 | static String getKotlinDataClass(String packageName) { 53 | return """ 54 | package ${packageName} 55 | 56 | data class Foo(val lable: String) 57 | 58 | """.stripIndent() 59 | } 60 | 61 | static String getRs() { 62 | return """ 63 | #pragma version(1) 64 | #pragma rs java_package_name(com.example.myapplication) 65 | 66 | static void addintAccum(int *accum, int val) { 67 | *accum += val; 68 | } 69 | """.stripIndent() 70 | } 71 | 72 | static String getXmlGenericLayout() { 73 | return ''' 74 | 79 | 84 | 85 | '''.stripIndent() 86 | } 87 | 88 | static String getXmlManifest(String appActivity, String libPackage, String libraryActivity) { 89 | return """ 90 | 91 | 92 | 93 | 97 | 98 | 99 | 100 | 101 | 102 | 104 | 105 | 106 | 107 | 108 | """.stripIndent() 109 | } 110 | 111 | static String getXmlEmptyManifest() { 112 | return ''' 113 | 114 | 115 | '''.stripIndent() 116 | } 117 | 118 | static String getXmlStrings() { 119 | return ''' 120 | 121 | Android Gradle 122 | 123 | '''.stripIndent() 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradle/android/CompileLibraryResourcesWorkaroundTest.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android 2 | 3 | import org.gradle.android.workarounds.CompileLibraryResourcesWorkaround 4 | import org.junit.Assume 5 | import spock.lang.Issue 6 | 7 | @MultiVersionTest 8 | class CompileLibraryResourcesWorkaroundTest extends AbstractTest { 9 | def "warns when experimental flags are not provided"() { 10 | Assume.assumeTrue(TestVersions.latestAndroidVersionForCurrentJDK() >= Versions.android("7.0.0-alpha09")) 11 | Assume.assumeTrue(TestVersions.latestAndroidVersionForCurrentJDK() < Versions.android("7.2.0-beta01")) 12 | 13 | SimpleAndroidApp.builder(temporaryFolder.root, cacheDir) 14 | .withAndroidVersion(TestVersions.latestAndroidVersionForCurrentJDK()) 15 | .withKotlinDisabled() 16 | .build() 17 | .writeProject() 18 | 19 | when: 20 | def result = withGradleVersion(TestVersions.latestGradleVersion().version) 21 | .withProjectDir(temporaryFolder.root) 22 | .withArguments( 23 | "-P${CompileLibraryResourcesWorkaround.ENABLE_SOURCE_SET_PATHS_MAP}=false", 24 | "-P${CompileLibraryResourcesWorkaround.CACHE_COMPILE_LIB_RESOURCES}=false", 25 | 'assembleDebug' 26 | ) 27 | .build() 28 | 29 | then: 30 | result.output.count(warningForAndroidVersion(TestVersions.latestAndroidVersionForCurrentJDK().toString())) == 1 31 | 32 | when: 33 | result = withGradleVersion(TestVersions.latestGradleVersion().version) 34 | .withProjectDir(temporaryFolder.root) 35 | .withArguments( 36 | "-P${CompileLibraryResourcesWorkaround.ENABLE_SOURCE_SET_PATHS_MAP}=false", 37 | "-P${CompileLibraryResourcesWorkaround.CACHE_COMPILE_LIB_RESOURCES}=false", 38 | 'assembleDebug' 39 | ) 40 | .build() 41 | 42 | then: 43 | result.output.count(warningForAndroidVersion(TestVersions.latestAndroidVersionForCurrentJDK().toString())) == 1 44 | } 45 | 46 | def "does not warn when experimental flags are provided"() { 47 | Assume.assumeTrue(TestVersions.latestAndroidVersionForCurrentJDK() >= Versions.android("7.0.0-alpha09")) 48 | Assume.assumeTrue(TestVersions.latestAndroidVersionForCurrentJDK() <= Versions.android("7.2.0-beta01")) 49 | 50 | SimpleAndroidApp.builder(temporaryFolder.root, cacheDir) 51 | .withAndroidVersion(TestVersions.latestAndroidVersionForCurrentJDK()) 52 | .withKotlinDisabled() 53 | .build() 54 | .writeProject() 55 | 56 | when: 57 | def result = withGradleVersion(TestVersions.latestGradleVersion().version) 58 | .withProjectDir(temporaryFolder.root) 59 | .withArguments( 60 | "-P${CompileLibraryResourcesWorkaround.ENABLE_SOURCE_SET_PATHS_MAP}=true", 61 | "-P${CompileLibraryResourcesWorkaround.CACHE_COMPILE_LIB_RESOURCES}=true", 62 | 'assembleDebug' 63 | ) 64 | .build() 65 | 66 | then: 67 | result.output.count(warningForAndroidVersion(TestVersions.latestAndroidVersionForCurrentJDK().toString())) == 0 68 | } 69 | 70 | def "does not warn for versions that do not support experimental flag"() { 71 | Assume.assumeTrue(TestVersions.latestAndroidVersionForCurrentJDK() < Versions.android("7.0.0-alpha09")) 72 | 73 | SimpleAndroidApp.builder(temporaryFolder.root, cacheDir) 74 | .withAndroidVersion(TestVersions.latestAndroidVersionForCurrentJDK()) 75 | .withKotlinDisabled() 76 | .build() 77 | .writeProject() 78 | 79 | when: 80 | def result = withGradleVersion(TestVersions.latestGradleVersion().version) 81 | .withProjectDir(temporaryFolder.root) 82 | .withArguments( 83 | "-P${CompileLibraryResourcesWorkaround.ENABLE_SOURCE_SET_PATHS_MAP}=false", 84 | "-P${CompileLibraryResourcesWorkaround.CACHE_COMPILE_LIB_RESOURCES}=false", 85 | 'assembleDebug' 86 | ) 87 | .build() 88 | 89 | then: 90 | result.output.count(warningForAndroidVersion(TestVersions.latestAndroidVersionForCurrentJDK().toString())) == 0 91 | } 92 | 93 | @Issue("https://github.com/gradle/android-cache-fix-gradle-plugin/issues/234") 94 | def "does not warn about experimental flags when applied from a kotlin script plugin"() { 95 | SimpleAndroidApp.builder(temporaryFolder.root, cacheDir) 96 | .withAndroidVersion(TestVersions.latestAndroidVersionForCurrentJDK()) 97 | .withKotlinDisabled() 98 | .build() 99 | .writeProject() 100 | 101 | file('buildSrc/src/main/kotlin').mkdirs() 102 | file('buildSrc/build.gradle.kts') << """ 103 | plugins { 104 | `kotlin-dsl` 105 | } 106 | 107 | repositories { 108 | google() 109 | mavenCentral() 110 | maven { 111 | url = uri("${SimpleAndroidApp.localRepo}") 112 | } 113 | } 114 | 115 | dependencies { 116 | implementation("${SimpleAndroidApp.pluginGroupId}:android-cache-fix-gradle-plugin:${SimpleAndroidApp.pluginVersion}") 117 | implementation("com.android.tools.build:gradle:${TestVersions.latestAndroidVersionForCurrentJDK().toString()}") 118 | } 119 | """ 120 | file('buildSrc/src/main/kotlin/script-plugin.gradle.kts') << """ 121 | plugins { 122 | id("org.gradle.android.cache-fix") 123 | } 124 | """ 125 | file('app/build.gradle') << """ 126 | apply plugin: "script-plugin" 127 | """ 128 | 129 | when: 130 | def result = withGradleVersion(TestVersions.latestGradleVersion().version) 131 | .withProjectDir(temporaryFolder.root) 132 | .withArguments( 133 | "-P${CompileLibraryResourcesWorkaround.ENABLE_SOURCE_SET_PATHS_MAP}=true", 134 | "-P${CompileLibraryResourcesWorkaround.CACHE_COMPILE_LIB_RESOURCES}=true", 135 | 'assembleDebug' 136 | ) 137 | .build() 138 | 139 | then: 140 | result.output.count(warningForAndroidVersion(TestVersions.latestAndroidVersionForCurrentJDK().toString())) == 0 141 | } 142 | 143 | private static String warningForAndroidVersion(String androidVersion) { 144 | return Warnings.USE_COMPILE_LIBRARY_RESOURCES_EXPERIMENTAL.warning.replaceAll('Android plugin [^\\s]+', "Android plugin ${androidVersion}") 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradle/android/ConfigurationCachingTest.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android 2 | 3 | import org.gradle.testkit.runner.BuildResult 4 | 5 | @MultiVersionTest 6 | class ConfigurationCachingTest extends AbstractTest { 7 | private static final VersionNumber SUPPORTED_KOTLIN_VERSION = TestVersions.latestSupportedKotlinVersion() 8 | static final String CC_PROBLEMS_FOUND = "problems were found storing the configuration cache" 9 | 10 | def "plugin is compatible with configuration cache"() { 11 | given: 12 | SimpleAndroidApp.builder(temporaryFolder.root, cacheDir) 13 | .withAndroidVersion(TestVersions.latestAndroidVersionForCurrentJDK()) 14 | .withKotlinVersion(SUPPORTED_KOTLIN_VERSION) 15 | .build() 16 | .writeProject() 17 | 18 | when: 19 | def result = withGradleVersion(TestVersions.latestGradleVersion().version) 20 | .withProjectDir(temporaryFolder.root) 21 | .withArguments('--configuration-cache', 'assembleDebug') 22 | .build() 23 | 24 | then: 25 | assertNoConfigCacheProblemsFound(result) 26 | 27 | when: 28 | result = withGradleVersion(TestVersions.latestGradleVersion().version) 29 | .withProjectDir(temporaryFolder.root) 30 | .withArguments('--configuration-cache', 'assembleDebug') 31 | .build() 32 | 33 | then: 34 | assertConfigurationCacheIsReused(result) 35 | } 36 | 37 | void assertConfigurationCacheIsReused(BuildResult result) { 38 | assert result.output.contains('Reusing configuration cache.') 39 | } 40 | 41 | void assertNoConfigCacheProblemsFound(BuildResult result) { 42 | assert !result.output.contains(CC_PROBLEMS_FOUND) || result.output.contains("0 ${CC_PROBLEMS_FOUND}") 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradle/android/CrossVersionOutcomeAndRelocationTest.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android 2 | 3 | import com.google.common.collect.ImmutableMap 4 | import groovy.json.JsonSlurper 5 | import org.gradle.testkit.runner.BuildResult 6 | import org.gradle.util.GradleVersion 7 | import spock.lang.Unroll 8 | 9 | import static org.gradle.android.TestVersions.latestKotlinVersionForGradleVersion 10 | import static org.gradle.testkit.runner.TaskOutcome.FROM_CACHE 11 | 12 | @MultiVersionTest 13 | class CrossVersionOutcomeAndRelocationTest extends AbstractTest { 14 | 15 | @Unroll 16 | def "simple Android app is relocatable with #gradleVersion and Android plugin #androidVersion"() { 17 | assert gradleVersion instanceof GradleVersion 18 | assert androidVersion instanceof VersionNumber 19 | 20 | println "> Using Android plugin $androidVersion" 21 | println "> Running with $gradleVersion" 22 | 23 | def originalDir = temporaryFolder.newFolder() 24 | SimpleAndroidApp.builder(originalDir, cacheDir) 25 | .withAndroidVersion(androidVersion) 26 | .withKotlinVersion(latestKotlinVersionForGradleVersion(gradleVersion)) 27 | .build() 28 | .writeProject() 29 | 30 | def relocatedDir = temporaryFolder.newFolder() 31 | SimpleAndroidApp.builder(relocatedDir, cacheDir) 32 | .withAndroidVersion(androidVersion) 33 | .withKotlinVersion(latestKotlinVersionForGradleVersion(gradleVersion)) 34 | .build() 35 | .writeProject() 36 | 37 | def expectedResults = expectedResults(androidVersion, latestKotlinVersionForGradleVersion(gradleVersion)) 38 | 39 | println expectedResults.describe() 40 | 41 | cacheDir.deleteDir() 42 | cacheDir.mkdirs() 43 | 44 | withGradleVersion(gradleVersion.version) 45 | .withProjectDir(originalDir) 46 | .withArguments("assemble", "createFullJarDebug", "createFullJarRelease", "--build-cache", "--stacktrace") 47 | .build() 48 | 49 | when: 50 | def result = withGradleVersion(gradleVersion.version) 51 | .withProjectDir(relocatedDir) 52 | .withArguments("assemble", "createFullJarDebug", "createFullJarRelease", "--build-cache", "--stacktrace") 53 | .build() 54 | 55 | then: 56 | expectedResults.verify(result) 57 | 58 | cleanup: 59 | originalDir.deleteDir() 60 | relocatedDir.deleteDir() 61 | 62 | where: 63 | //noinspection GroovyAssignabilityCheck 64 | [androidVersion, gradleVersion] << TestVersions.allCandidateTestVersions.entries().collect { [it.key, it.value] } 65 | } 66 | 67 | static class ExpectedResults { 68 | private final Map outcomes 69 | 70 | ExpectedResults(Map outcomes) { 71 | this.outcomes = outcomes 72 | } 73 | 74 | String describe() { 75 | "> Expecting ${outcomes.values().count(FROM_CACHE)} tasks out of ${outcomes.size()} to be cached" 76 | } 77 | 78 | boolean verify(BuildResult result) { 79 | boolean allMatched = true 80 | def remainingTasks = result.tasks.collect { it.path } 81 | outcomes.each { taskName, expectedOutcome -> 82 | def taskOutcome = result.task(taskName)?.outcome 83 | if (taskOutcome == null) { 84 | println "> Task '$taskName' was expected to execute but did not" 85 | allMatched = false 86 | } else if (expectedOutcome != ExpectedOutcome.UNKNOWN && taskOutcome.name() != expectedOutcome.name()) { 87 | println "> Task '$taskName' was $taskOutcome but should have been $expectedOutcome" 88 | allMatched = false 89 | } 90 | remainingTasks.remove(taskName) 91 | } 92 | if (!remainingTasks.empty) { 93 | remainingTasks.each { taskName -> 94 | def taskOutcome = result.task(taskName)?.outcome 95 | println "> Task '$taskName' executed with outcome $taskOutcome but was not expected" 96 | allMatched = false 97 | } 98 | } 99 | return allMatched 100 | } 101 | } 102 | 103 | private enum ExpectedOutcome { 104 | SUCCESS, 105 | FAILED, 106 | UP_TO_DATE, 107 | SKIPPED, 108 | FROM_CACHE, 109 | NO_SOURCE, 110 | UNKNOWN; // represents tasks where the outcome is indeterminant 111 | } 112 | 113 | private static class ExpectedOutcomeBuilder { 114 | private Set seen = [] 115 | private ImmutableMap.Builder mapBuilder = new ImmutableMap.Builder() 116 | 117 | private void checkIfSeen(String key) { 118 | if (seen.contains(key)) { 119 | throw new IllegalArgumentException("The task ${key} already has an expected value!") 120 | } else { 121 | seen.add(key) 122 | } 123 | } 124 | 125 | ExpectedOutcomeBuilder expect(String key, String outcome) { 126 | checkIfSeen(key) 127 | mapBuilder.put(key, ExpectedOutcome.valueOf(outcome)) 128 | return this 129 | } 130 | 131 | ImmutableMap build() { 132 | return mapBuilder.build() 133 | } 134 | } 135 | 136 | private static ExpectedResults expectedResults(VersionNumber androidVersion, VersionNumber kotlinVersion) { 137 | def builder = new ExpectedOutcomeBuilder() 138 | def path = "expectedOutcomes/${androidVersion.major}.${androidVersion.minor}_outcomes.json" 139 | def outcomesResource = CrossVersionOutcomeAndRelocationTest.classLoader.getResource(path) 140 | 141 | if (outcomesResource == null) { 142 | throw new IllegalStateException("Could not find expectedOutcomes/${androidVersion}_outcomes.json - make sure an outcomes file exists for this version!") 143 | } 144 | 145 | Map json = new JsonSlurper().parse(outcomesResource) as Map 146 | 147 | json.each { task, outcome -> 148 | builder.expect(task as String, outcome as String) 149 | } 150 | 151 | if (kotlinVersion >= VersionNumber.parse("1.6.0")) { 152 | builder.expect(":app:buildKotlinToolingMetadata", "SUCCESS") 153 | } 154 | 155 | new ExpectedResults( 156 | builder.build() 157 | ) 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradle/android/JdkImageWorkaroundDescriptorTest.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android 2 | 3 | import com.google.common.collect.Sets 4 | import org.gradle.android.workarounds.JdkImageWorkaround 5 | import spock.lang.Specification 6 | import spock.lang.Unroll 7 | 8 | import java.lang.module.ModuleDescriptor 9 | 10 | class JdkImageWorkaroundDescriptorTest extends Specification { 11 | def "normalizes module descriptors with different orders in the values"() { 12 | given: 13 | def serialized1 = JdkImageWorkaround.ExtractJdkImageTransform.serializeDescriptor(descriptor(["org.foo", "org.bar"], ["baz", "fizz"])) 14 | def serialized2 = JdkImageWorkaround.ExtractJdkImageTransform.serializeDescriptor(descriptor(["org.bar", "org.foo"], ["fizz", "baz"])) 15 | 16 | expect: 17 | serialized1 == serialized2 18 | } 19 | 20 | def "descriptors with different values are serialized differently"() { 21 | given: 22 | def serialized1 = JdkImageWorkaround.ExtractJdkImageTransform.serializeDescriptor(descriptor(["org.foo", "org.bar"], ["baz", "fizz"])) 23 | def serialized2 = JdkImageWorkaround.ExtractJdkImageTransform.serializeDescriptor(descriptor(["org.bar", "org.foo", "org.baz"], ["baz", "fizz"])) 24 | 25 | expect: 26 | serialized1 != serialized2 27 | } 28 | 29 | @Unroll 30 | def "all descriptor values are captured (#modifier.trim())"() { 31 | ModuleDescriptor descriptor = builder 32 | .requires("foo").requires("bar") 33 | .uses("org.baz").uses("org.fizz") 34 | .exports("org.exports", ["exportsTarget1", "exportsTarget2"] as Set) 35 | .provides("org.provides", ["org.provider1", "org.provider2"]) 36 | .with { 37 | modifier == "" ? opens("org.opens", ["opensTarget1", "opensTarget2"] as Set) : it 38 | }.build() 39 | 40 | expect: 41 | JdkImageWorkaround.ExtractJdkImageTransform.serializeDescriptor(descriptor) == "${modifier}module { name: myModule, " + 42 | "[bar, foo, mandated java.base], " + 43 | "uses: [org.baz, org.fizz], " + 44 | "exports: [org.exports to [exportsTarget1, exportsTarget2]], " + 45 | (modifier == "" ? "opens: [org.opens to [opensTarget1, opensTarget2]], " : "") + 46 | "provides: [org.provides with [org.provider1, org.provider2]] }" 47 | 48 | where: 49 | builder | modifier 50 | ModuleDescriptor.newModule("myModule") | "" 51 | ModuleDescriptor.newOpenModule("myModule") | "open " 52 | } 53 | 54 | static def descriptor(List packages, List values) { 55 | ModuleDescriptor.Builder builder = ModuleDescriptor.newModule("myModule") 56 | values.each { builder.requires(it) } 57 | packages.each { builder.uses(it) } 58 | packages.each { builder.exports("${it}.exports", Sets.newLinkedHashSet(values)) } 59 | packages.each { builder.opens("${it}.opens", Sets.newLinkedHashSet(values)) } 60 | packages.each { builder.provides("${it}.provides", values.collect { v -> "org.${v}".toString() }) } 61 | return builder.build() 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradle/android/MergeJavaResourcesWorkaroundTest.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android 2 | 3 | import org.gradle.testkit.runner.BuildResult 4 | import org.gradle.testkit.runner.TaskOutcome 5 | import spock.lang.Issue 6 | import spock.lang.Unroll 7 | 8 | @MultiVersionTest 9 | class MergeJavaResourcesWorkaroundTest extends AbstractTest { 10 | @Unroll 11 | @Issue('https://github.com/gradle/android-cache-fix-gradle-plugin/issues/78') 12 | def "workaround does not cause task to be skipped when inputs are empty (Android #androidVersion)"() { 13 | SimpleAndroidApp.builder(temporaryFolder.root, cacheDir) 14 | .withAndroidVersion(androidVersion) 15 | .withKotlinDisabled() 16 | .build() 17 | .writeProject() 18 | 19 | cacheDir.deleteDir() 20 | cacheDir.mkdirs() 21 | 22 | when: 23 | BuildResult buildResult = withGradleVersion(TestVersions.latestSupportedGradleVersionFor(androidVersion).version) 24 | .forwardOutput() 25 | .withProjectDir(temporaryFolder.root) 26 | .withArguments("assemble", "--stacktrace") 27 | .build() 28 | 29 | then: 30 | buildResult.task(':app:mergeDebugJavaResource').outcome == TaskOutcome.SUCCESS 31 | buildResult.task(':app:mergeReleaseJavaResource').outcome == TaskOutcome.SUCCESS 32 | buildResult.task(':library:mergeDebugJavaResource').outcome == TaskOutcome.SUCCESS 33 | buildResult.task(':library:mergeReleaseJavaResource').outcome == TaskOutcome.SUCCESS 34 | 35 | where: 36 | androidVersion << TestVersions.latestAndroidVersions 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradle/android/MultiVersionTest.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android 2 | 3 | import java.lang.annotation.ElementType 4 | import java.lang.annotation.Inherited 5 | import java.lang.annotation.Retention 6 | import java.lang.annotation.RetentionPolicy 7 | import java.lang.annotation.Target 8 | 9 | /** 10 | * Represents tests that span multiple versions of Android Gradle Plugin and need to be executed 11 | * with multiple versions of the JDK. 12 | */ 13 | @Inherited 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Target(ElementType.TYPE) 16 | @interface MultiVersionTest { } 17 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradle/android/PluginApplicationTest.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android 2 | 3 | import spock.lang.Unroll 4 | 5 | import static java.util.regex.Pattern.quote 6 | 7 | class PluginApplicationTest extends AbstractTest { 8 | 9 | @Unroll 10 | def "does not apply workarounds with Android #androidVersion"() { 11 | def projectDir = temporaryFolder.newFolder() 12 | SimpleAndroidApp.builder(projectDir, cacheDir) 13 | .withAndroidVersion(androidVersion) 14 | .withKotlinVersion(VersionNumber.parse(TestVersions.kotlinVersionCompatibleWithOlderAgp)) 15 | .build() 16 | .writeProject() 17 | 18 | expect: 19 | def result = withGradleVersion(TestVersions.latestGradleVersion().version) 20 | .withProjectDir(projectDir) 21 | .withArguments("tasks", "--stacktrace") 22 | .buildAndFail() 23 | result.output =~ /Android plugin ${quote(androidVersion)} is not supported by Android cache fix plugin. For older Android Gradle Plugin versions, please use Android Cache Fix Plugin 2.4.6/ 24 | 25 | where: 26 | androidVersion << ["4.2.2"] 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradle/android/PluginBlockTest.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android 2 | 3 | import org.gradle.testkit.runner.TaskOutcome 4 | 5 | // AGP 7.4 surfaced issues with the Plugin block configuration https://github.com/gradle/android-cache-fix-gradle-plugin/issues/412 6 | // Current Gradle Runner tests are using buildscript block. This test covers the scenario of declaring the plugin in the 7 | // plugins { block of the root build.gradle for these use cases: 8 | // * Plugin apply by default 9 | // * Plugin is not applied 10 | @MultiVersionTest 11 | class PluginBlockTest extends AbstractTest { 12 | 13 | def "project builds when plugin is defined in the Plugin block but is not applied"() { 14 | 15 | def projectDir = temporaryFolder.newFolder() 16 | 17 | SimpleAndroidApp.builder(projectDir, cacheDir) 18 | .withKotlinVersion(TestVersions.latestSupportedKotlinVersion()) 19 | .withPluginsBlockEnabled() 20 | .build() 21 | .writeProject() 22 | 23 | when: 24 | def result = withGradleVersion(TestVersions.latestGradleVersion().version) 25 | .withProjectDir(projectDir) 26 | .withArguments("assembleDebug", "--stacktrace", "--configuration-cache") 27 | .build() 28 | 29 | then: 30 | result.task(":library:assembleDebug").outcome == TaskOutcome.SUCCESS 31 | result.task(":library:compileDebugLibraryResources").outcome == TaskOutcome.SUCCESS 32 | } 33 | 34 | def "project builds when plugin is defined in the Plugin block and is applied"() { 35 | 36 | def projectDir = temporaryFolder.newFolder() 37 | 38 | SimpleAndroidApp.builder(projectDir, cacheDir) 39 | .withKotlinVersion(TestVersions.latestSupportedKotlinVersion()) 40 | .withPluginsBlockEnabledApplyingThePlugin() 41 | .build() 42 | .writeProject() 43 | 44 | when: 45 | def result = withGradleVersion(TestVersions.latestGradleVersion().version) 46 | .withProjectDir(projectDir) 47 | .withArguments("assembleDebug", "--stacktrace", "--configuration-cache") 48 | .build() 49 | 50 | then: 51 | result.task(":library:assembleDebug").outcome == TaskOutcome.SUCCESS 52 | result.task(":library:compileDebugLibraryResources").outcome == TaskOutcome.SUCCESS 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradle/android/RerunTasksTest.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android 2 | 3 | import org.gradle.testkit.runner.TaskOutcome 4 | import org.junit.Assume 5 | 6 | @MultiVersionTest 7 | class RerunTasksTest extends AbstractTest { 8 | 9 | def "test with configuration cache and --rerun-tasks works"() { 10 | Assume.assumeTrue(TestVersions.latestAndroidVersionForCurrentJDK() >= VersionNumber.parse("4.2.0-alpha01")) 11 | 12 | def projectDir = temporaryFolder.newFolder() 13 | SimpleAndroidApp.builder(projectDir, cacheDir) 14 | .withKotlinVersion(TestVersions.latestSupportedKotlinVersion()) 15 | .build() 16 | .writeProject() 17 | 18 | withGradleVersion(TestVersions.latestGradleVersion().version) 19 | .withProjectDir(projectDir) 20 | .withArguments("assembleDebug", "--stacktrace", "--rerun-tasks", "--configuration-cache") 21 | .build() 22 | 23 | when: 24 | def result = withGradleVersion(TestVersions.latestGradleVersion().version) 25 | .withProjectDir(projectDir) 26 | .withArguments("assembleDebug", "--stacktrace", "--rerun-tasks", "--configuration-cache") 27 | .build() 28 | 29 | then: 30 | result.task(":library:assembleDebug").outcome == TaskOutcome.SUCCESS 31 | result.task(":library:compileDebugLibraryResources").outcome == TaskOutcome.SUCCESS 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradle/android/TaskAvoidanceTest.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android 2 | 3 | import spock.lang.Unroll 4 | 5 | @MultiVersionTest 6 | class TaskAvoidanceTest extends AbstractTest { 7 | @Unroll 8 | def "Source Tasks are avoided with #gradleVersion and Android plugin #androidVersion"() { 9 | given: 10 | SimpleAndroidApp.builder(temporaryFolder.root, cacheDir) 11 | .withAndroidVersion(androidVersion) 12 | .withKotlinDisabled() 13 | .build() 14 | .writeProject() 15 | 16 | file('build.gradle') << """ 17 | allprojects { 18 | tasks.withType(SourceTask).configureEach { 19 | println "configuring \$it" 20 | } 21 | } 22 | """ 23 | 24 | when: 25 | def result = withGradleVersion(gradleVersion.version) 26 | .withProjectDir(temporaryFolder.root) 27 | .withArguments('help') 28 | .build() 29 | 30 | then: 31 | !result.output.contains("configuring") 32 | 33 | where: 34 | [androidVersion, gradleVersion] << TestVersions.allCandidateTestVersions.entries().collect { [it.key, it.value] } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradle/android/TestVersions.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android 2 | 3 | import com.google.common.collect.ImmutableMultimap 4 | import com.google.common.collect.ImmutableSortedSet 5 | import com.google.common.collect.Multimap 6 | import groovy.json.JsonSlurper 7 | import org.gradle.util.GradleVersion 8 | 9 | class TestVersions { 10 | static final Set TESTED_GRADLE_VERSIONS 11 | static final Set TESTED_ANDROID_VERSIONS 12 | static final Multimap TESTED_VERSIONS_MATRIX 13 | 14 | static { 15 | def versions = new JsonSlurper().parse(AndroidCacheFixPlugin.classLoader.getResource("versions.json")) 16 | 17 | def builder = ImmutableMultimap.builder() 18 | versions.testedVersions.each { String androidVersion, List gradleVersions -> 19 | builder.putAll(Versions.android(androidVersion), gradleVersions.collect { Versions.gradle(it) }) 20 | } 21 | def matrix = builder.build() 22 | 23 | TESTED_VERSIONS_MATRIX = matrix 24 | TESTED_ANDROID_VERSIONS = ImmutableSortedSet.copyOf(matrix.keySet()) 25 | TESTED_GRADLE_VERSIONS = ImmutableSortedSet.copyOf(matrix.values()) 26 | } 27 | 28 | static Multimap getAllCandidateTestVersions() { 29 | def testedVersion = System.getProperty('org.gradle.android.testVersion') 30 | if (testedVersion) { 31 | return ImmutableMultimap.copyOf(TESTED_VERSIONS_MATRIX.entries().findAll {it.key == VersionNumber.parse(testedVersion) }) 32 | } else { 33 | return TESTED_VERSIONS_MATRIX 34 | } 35 | } 36 | 37 | static VersionNumber latestAndroidVersionForCurrentJDK() { 38 | return allCandidateTestVersions.keySet().max() 39 | } 40 | 41 | static GradleVersion latestGradleVersion() { 42 | return allCandidateTestVersions.values().max() 43 | } 44 | 45 | static GradleVersion latestSupportedGradleVersionFor(String androidVersion) { 46 | return latestSupportedGradleVersionFor(VersionNumber.parse(androidVersion)) 47 | } 48 | 49 | static GradleVersion latestSupportedGradleVersionFor(VersionNumber androidVersion) { 50 | return allCandidateTestVersions.asMap().find {it.key.major == androidVersion.major && it.key.minor == androidVersion.minor }?.value?.max() 51 | } 52 | 53 | static VersionNumber getLatestVersionForAndroid(String version) { 54 | VersionNumber versionNumber = VersionNumber.parse(version) 55 | return allCandidateTestVersions.keySet().findAll { it.major == versionNumber.major && it.minor == versionNumber.minor }?.max() 56 | } 57 | 58 | static List getLatestAndroidVersions() { 59 | def minorVersions = allCandidateTestVersions.keySet().collect { "${it.major}.${it.minor}" } 60 | return minorVersions.collect { getLatestVersionForAndroid(it) } 61 | } 62 | 63 | static String kotlinVersion = "2.0.21" 64 | // AGP versions <= 7.0 can't use the kotlin-android plugin version 2.0 65 | static String kotlinVersionCompatibleWithOlderAgp = "1.9.0" 66 | 67 | static VersionNumber latestSupportedKotlinVersion() { 68 | // version 7.1.3 or higher should be used with kotlin-android plugin 2 69 | if(latestAndroidVersionForCurrentJDK() <= VersionNumber.parse("7.0.4")) { 70 | return VersionNumber.parse(kotlinVersionCompatibleWithOlderAgp) 71 | } else { 72 | return VersionNumber.parse(kotlinVersion) 73 | } 74 | } 75 | 76 | static VersionNumber latestKotlinVersionForGradleVersion(GradleVersion gradleVersion) { 77 | return latestSupportedKotlinVersion() 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradle/android/VersionsTest.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android 2 | 3 | import spock.lang.Specification 4 | 5 | class VersionsTest extends Specification { 6 | def "earliest tested version corresponds to minimum supported version"() { 7 | def alphaOfEarliest = alphaVersionOf(TestVersions.TESTED_ANDROID_VERSIONS.min()) 8 | 9 | expect: 10 | alphaOfEarliest == Versions.MINIMUM_ANDROID_VERSION 11 | } 12 | 13 | static VersionNumber alphaVersionOf(VersionNumber versionNumber) { 14 | return Versions.android("${versionNumber.major}.${versionNumber.minor}.0-alpha01") 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradle/android/WorkaroundTest.groovy: -------------------------------------------------------------------------------- 1 | package org.gradle.android 2 | 3 | import spock.lang.Specification 4 | import spock.lang.Unroll 5 | 6 | class WorkaroundTest extends Specification { 7 | @Unroll 8 | def "applies the right workarounds for Android #androidVersion"() { 9 | def possibleWorkarounds = AndroidCacheFixPlugin.initializeWorkarounds() 10 | def workarounds = AndroidCacheFixPlugin.getWorkaroundsToApply(Versions.android(androidVersion), null, possibleWorkarounds) 11 | expect: 12 | workarounds.collect { it.class.simpleName.replaceAll(/Workaround/, "") }.sort() == expectedWorkarounds.sort() 13 | where: 14 | androidVersion | expectedWorkarounds 15 | "8.9" | ['JdkImage'] 16 | "8.8" | ['JdkImage'] 17 | "8.7" | ['JdkImage'] 18 | "8.6" | ['JdkImage'] 19 | "8.5" | ['JdkImage'] 20 | "8.4" | ['JdkImage'] 21 | "8.3" | ['MergeSourceSetFolders', 'JdkImage'] 22 | "8.2" | ['MergeSourceSetFolders', 'JdkImage', 'PackageForUnitTest'] 23 | "8.1" | ['MergeSourceSetFolders', 'JdkImage', 'PackageForUnitTest'] 24 | "8.0" | ['MergeSourceSetFolders', 'ZipMergingTask', 'JdkImage', 'PackageForUnitTest'] 25 | "7.4" | ['MergeSourceSetFolders', 'ZipMergingTask', 'JdkImage', 'PackageForUnitTest'] 26 | "7.3" | ['MergeSourceSetFolders', 'ZipMergingTask', 'JdkImage', 'PackageForUnitTest'] 27 | "7.2" | ['MergeSourceSetFolders', 'ZipMergingTask', 'JdkImage', 'PackageForUnitTest'] 28 | "7.1" | ['BundleLibraryClasses', 'CompileLibraryResources', 'DataBindingMergeDependencyArtifacts', 'LibraryJniLibs', 'MergeNativeLibs', 'MergeSourceSetFolders', 'StripDebugSymbols', 'ZipMergingTask', 'JdkImage', 'PackageForUnitTest'] 29 | "7.0" | ['BundleLibraryClasses', 'CompileLibraryResources', 'DataBindingMergeDependencyArtifacts', 'LibraryJniLibs', 'MergeNativeLibs', 'MergeSourceSetFolders', 'StripDebugSymbols', 'ZipMergingTask', 'PackageForUnitTest'] 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/resources/SpockConfig.groovy: -------------------------------------------------------------------------------- 1 | import org.gradle.android.MultiVersionTest 2 | 3 | def testAndroidVersion = System.getProperty('org.gradle.android.testVersion') 4 | 5 | runner { 6 | if (testAndroidVersion) { 7 | include MultiVersionTest 8 | } else { 9 | exclude MultiVersionTest 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/test/resources/expectedOutcomes/8.10_outcomes.json: -------------------------------------------------------------------------------- 1 | { 2 | ":app:assemble" : "SUCCESS", 3 | ":app:assembleDebug" : "SUCCESS", 4 | ":app:assembleRelease" : "SUCCESS", 5 | ":app:checkDebugAarMetadata" : "SUCCESS", 6 | ":app:checkDebugDuplicateClasses" : "SUCCESS", 7 | ":app:checkReleaseAarMetadata" : "SUCCESS", 8 | ":app:checkReleaseDuplicateClasses" : "SUCCESS", 9 | ":app:collectReleaseDependencies" : "SUCCESS", 10 | ":app:compileDebugJavaWithJavac" : "FROM_CACHE", 11 | ":app:compileDebugKotlin" : "FROM_CACHE", 12 | ":app:compileDebugShaders" : "NO_SOURCE", 13 | ":app:compileReleaseArtProfile" : "FROM_CACHE", 14 | ":app:compileReleaseJavaWithJavac" : "FROM_CACHE", 15 | ":app:compileReleaseKotlin" : "FROM_CACHE", 16 | ":app:compileReleaseShaders" : "NO_SOURCE", 17 | ":app:compressDebugAssets" : "FROM_CACHE", 18 | ":app:compressReleaseAssets" : "FROM_CACHE", 19 | ":app:createDebugApkListingFileRedirect" : "SUCCESS", 20 | ":app:createDebugCompatibleScreenManifests" : "SUCCESS", 21 | ":app:createReleaseApkListingFileRedirect" : "SUCCESS", 22 | ":app:createReleaseCompatibleScreenManifests" : "SUCCESS", 23 | ":app:dataBindingGenBaseClassesDebug" : "FROM_CACHE", 24 | ":app:dataBindingGenBaseClassesRelease" : "FROM_CACHE", 25 | ":app:dataBindingMergeDependencyArtifactsDebug" : "SUCCESS", 26 | ":app:dataBindingMergeDependencyArtifactsRelease" : "SUCCESS", 27 | ":app:dataBindingTriggerDebug" : "SUCCESS", 28 | ":app:dataBindingTriggerRelease" : "SUCCESS", 29 | ":app:desugarDebugFileDependencies" : "FROM_CACHE", 30 | ":app:desugarReleaseFileDependencies" : "FROM_CACHE", 31 | ":app:dexBuilderDebug" : "FROM_CACHE", 32 | ":app:dexBuilderRelease" : "FROM_CACHE", 33 | ":app:extractDeepLinksDebug" : "FROM_CACHE", 34 | ":app:extractDeepLinksRelease" : "FROM_CACHE", 35 | ":app:extractReleaseNativeSymbolTables" : "NO_SOURCE", 36 | ":app:extractReleaseVersionControlInfo" : "SUCCESS", 37 | ":app:generateDebugAssets" : "UP_TO_DATE", 38 | ":app:generateDebugResources" : "FROM_CACHE", 39 | ":app:generateDebugResValues" : "FROM_CACHE", 40 | ":app:generateReleaseAssets" : "UP_TO_DATE", 41 | ":app:generateReleaseResources" : "FROM_CACHE", 42 | ":app:generateReleaseResValues" : "FROM_CACHE", 43 | ":app:javaPreCompileDebug" : "FROM_CACHE", 44 | ":app:javaPreCompileRelease" : "FROM_CACHE", 45 | ":app:kaptDebugKotlin" : "FROM_CACHE", 46 | ":app:kaptGenerateStubsDebugKotlin" : "FROM_CACHE", 47 | ":app:kaptGenerateStubsReleaseKotlin" : "FROM_CACHE", 48 | ":app:kaptReleaseKotlin" : "FROM_CACHE", 49 | ":app:mapDebugSourceSetPaths" : "SUCCESS", 50 | ":app:mapReleaseSourceSetPaths" : "SUCCESS", 51 | ":app:mergeDebugAssets" : "SUCCESS", 52 | ":app:mergeDebugGlobalSynthetics" : "FROM_CACHE", 53 | ":app:mergeDebugJavaResource" : "SUCCESS", 54 | ":app:mergeDebugJniLibFolders" : "SUCCESS", 55 | ":app:mergeDebugNativeDebugMetadata" : "NO_SOURCE", 56 | ":app:mergeDebugNativeLibs" : "NO_SOURCE", 57 | ":app:mergeDebugResources" : "FROM_CACHE", 58 | ":app:mergeDebugShaders" : "SUCCESS", 59 | ":app:mergeDexRelease" : "FROM_CACHE", 60 | ":app:mergeExtDexDebug" : "FROM_CACHE", 61 | ":app:mergeExtDexRelease" : "FROM_CACHE", 62 | ":app:mergeLibDexDebug" : "FROM_CACHE", 63 | ":app:mergeProjectDexDebug" : "FROM_CACHE", 64 | ":app:mergeReleaseArtProfile" : "SUCCESS", 65 | ":app:mergeReleaseAssets" : "SUCCESS", 66 | ":app:mergeReleaseGlobalSynthetics" : "FROM_CACHE", 67 | ":app:mergeReleaseJavaResource" : "SUCCESS", 68 | ":app:mergeReleaseJniLibFolders" : "SUCCESS", 69 | ":app:mergeReleaseNativeDebugMetadata" : "NO_SOURCE", 70 | ":app:mergeReleaseNativeLibs" : "NO_SOURCE", 71 | ":app:mergeReleaseResources" : "FROM_CACHE", 72 | ":app:mergeReleaseShaders" : "SUCCESS", 73 | ":app:optimizeReleaseResources" : "FROM_CACHE", 74 | ":app:packageDebug" : "SUCCESS", 75 | ":app:packageDebugResources" : "FROM_CACHE", 76 | ":app:packageReleaseResources" : "FROM_CACHE", 77 | ":app:parseDebugLocalResources" : "FROM_CACHE", 78 | ":app:parseReleaseLocalResources" : "FROM_CACHE", 79 | ":app:packageRelease" : "SUCCESS", 80 | ":app:preBuild" : "UP_TO_DATE", 81 | ":app:preDebugBuild" : "UP_TO_DATE", 82 | ":app:preReleaseBuild" : "UP_TO_DATE", 83 | ":app:processDebugJavaRes" : "SUCCESS", 84 | ":app:processDebugMainManifest" : "FROM_CACHE", 85 | ":app:processDebugManifest" : "FROM_CACHE", 86 | ":app:processDebugManifestForPackage" : "FROM_CACHE", 87 | ":app:processDebugResources" : "FROM_CACHE", 88 | ":app:processReleaseJavaRes" : "SUCCESS", 89 | ":app:processReleaseMainManifest" : "FROM_CACHE", 90 | ":app:processReleaseManifest" : "FROM_CACHE", 91 | ":app:processReleaseManifestForPackage" : "FROM_CACHE", 92 | ":app:processReleaseResources" : "FROM_CACHE", 93 | ":app:sdkReleaseDependencyData" : "SUCCESS", 94 | ":app:stripDebugDebugSymbols" : "NO_SOURCE", 95 | ":app:stripReleaseDebugSymbols" : "NO_SOURCE", 96 | ":app:validateSigningDebug" : "SUCCESS", 97 | ":app:writeDebugAppMetadata" : "SUCCESS", 98 | ":app:writeDebugSigningConfigVersions" : "SUCCESS", 99 | ":app:writeReleaseAppMetadata" : "SUCCESS", 100 | ":app:writeReleaseSigningConfigVersions" : "SUCCESS", 101 | ":app:mergeReleaseStartupProfile" : "SUCCESS", 102 | ":library:assemble" : "SUCCESS", 103 | ":library:assembleDebug" : "SUCCESS", 104 | ":library:assembleRelease" : "SUCCESS", 105 | ":library:bundleDebugAar" : "SUCCESS", 106 | ":library:bundleLibCompileToJarDebug" : "SUCCESS", 107 | ":library:bundleLibCompileToJarRelease" : "SUCCESS", 108 | ":library:bundleLibRuntimeToDirDebug" : "SUCCESS", 109 | ":library:bundleLibRuntimeToDirRelease" : "SUCCESS", 110 | ":library:bundleLibRuntimeToJarDebug" : "SUCCESS", 111 | ":library:bundleLibRuntimeToJarRelease" : "SUCCESS", 112 | ":library:bundleReleaseAar" : "SUCCESS", 113 | ":library:compileDebugJavaWithJavac" : "FROM_CACHE", 114 | ":library:compileDebugKotlin" : "FROM_CACHE", 115 | ":library:compileDebugLibraryResources" : "FROM_CACHE", 116 | ":library:compileDebugShaders" : "NO_SOURCE", 117 | ":library:compileReleaseJavaWithJavac" : "FROM_CACHE", 118 | ":library:compileReleaseKotlin" : "FROM_CACHE", 119 | ":library:compileReleaseLibraryResources" : "FROM_CACHE", 120 | ":library:compileReleaseShaders" : "NO_SOURCE", 121 | ":library:copyDebugJniLibsProjectAndLocalJars" : "SUCCESS", 122 | ":library:copyDebugJniLibsProjectOnly" : "SUCCESS", 123 | ":library:copyReleaseJniLibsProjectAndLocalJars" : "SUCCESS", 124 | ":library:copyReleaseJniLibsProjectOnly" : "SUCCESS", 125 | ":library:createFullJarDebug" : "SUCCESS", 126 | ":library:createFullJarRelease" : "SUCCESS", 127 | ":library:dataBindingGenBaseClassesDebug" : "FROM_CACHE", 128 | ":library:dataBindingGenBaseClassesRelease" : "FROM_CACHE", 129 | ":library:dataBindingMergeDependencyArtifactsDebug" : "SUCCESS", 130 | ":library:dataBindingMergeDependencyArtifactsRelease": "SUCCESS", 131 | ":library:dataBindingTriggerDebug" : "SUCCESS", 132 | ":library:dataBindingTriggerRelease" : "SUCCESS", 133 | ":library:extractDebugAnnotations" : "FROM_CACHE", 134 | ":library:extractDeepLinksDebug" : "FROM_CACHE", 135 | ":library:extractDeepLinksForAarDebug" : "FROM_CACHE", 136 | ":library:extractDeepLinksForAarRelease" : "FROM_CACHE", 137 | ":library:extractDeepLinksRelease" : "FROM_CACHE", 138 | ":library:extractReleaseAnnotations" : "FROM_CACHE", 139 | ":library:generateDebugAssets" : "UP_TO_DATE", 140 | ":library:generateDebugResources" : "FROM_CACHE", 141 | ":library:generateDebugResValues" : "FROM_CACHE", 142 | ":library:generateDebugRFile" : "FROM_CACHE", 143 | ":library:generateReleaseAssets" : "UP_TO_DATE", 144 | ":library:generateReleaseResources" : "FROM_CACHE", 145 | ":library:generateReleaseResValues" : "FROM_CACHE", 146 | ":library:generateReleaseRFile" : "FROM_CACHE", 147 | ":library:javaPreCompileDebug" : "FROM_CACHE", 148 | ":library:javaPreCompileRelease" : "FROM_CACHE", 149 | ":library:kaptDebugKotlin" : "FROM_CACHE", 150 | ":library:kaptGenerateStubsDebugKotlin" : "FROM_CACHE", 151 | ":library:kaptGenerateStubsReleaseKotlin" : "FROM_CACHE", 152 | ":library:kaptReleaseKotlin" : "FROM_CACHE", 153 | ":library:mapReleaseSourceSetPaths" : "SUCCESS", 154 | ":library:mergeDebugAssets" : "SUCCESS", 155 | ":library:mergeDebugConsumerProguardFiles" : "SUCCESS", 156 | ":library:mergeDebugGeneratedProguardFiles" : "SUCCESS", 157 | ":library:mergeDebugJavaResource" : "SUCCESS", 158 | ":library:mergeDebugJniLibFolders" : "SUCCESS", 159 | ":library:mergeDebugNativeLibs" : "NO_SOURCE", 160 | ":library:mergeDebugShaders" : "SUCCESS", 161 | ":library:mergeReleaseAssets" : "SUCCESS", 162 | ":library:mergeReleaseConsumerProguardFiles" : "SUCCESS", 163 | ":library:mergeReleaseGeneratedProguardFiles" : "SUCCESS", 164 | ":library:mergeReleaseJavaResource" : "SUCCESS", 165 | ":library:mergeReleaseJniLibFolders" : "SUCCESS", 166 | ":library:mergeReleaseNativeLibs" : "NO_SOURCE", 167 | ":library:mergeReleaseResources" : "FROM_CACHE", 168 | ":library:mergeReleaseShaders" : "SUCCESS", 169 | ":library:packageDebugResources" : "FROM_CACHE", 170 | ":library:packageReleaseResources" : "FROM_CACHE", 171 | ":library:parseDebugLocalResources" : "FROM_CACHE", 172 | ":library:parseReleaseLocalResources" : "FROM_CACHE", 173 | ":library:preBuild" : "UP_TO_DATE", 174 | ":library:preDebugBuild" : "UP_TO_DATE", 175 | ":library:prepareDebugArtProfile" : "SUCCESS", 176 | ":library:prepareLintJarForPublish" : "SUCCESS", 177 | ":library:prepareReleaseArtProfile" : "SUCCESS", 178 | ":library:preReleaseBuild" : "UP_TO_DATE", 179 | ":library:processDebugJavaRes" : "SUCCESS", 180 | ":library:processDebugManifest" : "FROM_CACHE", 181 | ":library:processReleaseJavaRes" : "SUCCESS", 182 | ":library:processReleaseManifest" : "FROM_CACHE", 183 | ":library:stripDebugDebugSymbols" : "NO_SOURCE", 184 | ":library:stripReleaseDebugSymbols" : "NO_SOURCE", 185 | ":library:syncDebugLibJars" : "FROM_CACHE", 186 | ":library:syncReleaseLibJars" : "FROM_CACHE", 187 | ":library:verifyReleaseResources" : "FROM_CACHE", 188 | ":library:writeDebugAarMetadata" : "SUCCESS", 189 | ":library:writeReleaseAarMetadata" : "SUCCESS", 190 | ":app:checkKotlinGradlePluginConfigurationErrors" : "SKIPPED", 191 | ":library:checkKotlinGradlePluginConfigurationErrors": "SKIPPED" 192 | } 193 | -------------------------------------------------------------------------------- /src/test/resources/expectedOutcomes/8.11_outcomes.json: -------------------------------------------------------------------------------- 1 | { 2 | ":app:assemble" : "SUCCESS", 3 | ":app:assembleDebug" : "SUCCESS", 4 | ":app:assembleRelease" : "SUCCESS", 5 | ":app:checkDebugAarMetadata" : "SUCCESS", 6 | ":app:checkDebugDuplicateClasses" : "SUCCESS", 7 | ":app:checkReleaseAarMetadata" : "SUCCESS", 8 | ":app:checkReleaseDuplicateClasses" : "SUCCESS", 9 | ":app:collectReleaseDependencies" : "SUCCESS", 10 | ":app:compileDebugJavaWithJavac" : "FROM_CACHE", 11 | ":app:compileDebugKotlin" : "FROM_CACHE", 12 | ":app:compileDebugShaders" : "NO_SOURCE", 13 | ":app:compileReleaseArtProfile" : "FROM_CACHE", 14 | ":app:compileReleaseJavaWithJavac" : "FROM_CACHE", 15 | ":app:compileReleaseKotlin" : "FROM_CACHE", 16 | ":app:compileReleaseShaders" : "NO_SOURCE", 17 | ":app:compressDebugAssets" : "FROM_CACHE", 18 | ":app:compressReleaseAssets" : "FROM_CACHE", 19 | ":app:createDebugApkListingFileRedirect" : "SUCCESS", 20 | ":app:createDebugCompatibleScreenManifests" : "SUCCESS", 21 | ":app:createReleaseApkListingFileRedirect" : "SUCCESS", 22 | ":app:createReleaseCompatibleScreenManifests" : "SUCCESS", 23 | ":app:dataBindingGenBaseClassesDebug" : "FROM_CACHE", 24 | ":app:dataBindingGenBaseClassesRelease" : "FROM_CACHE", 25 | ":app:dataBindingMergeDependencyArtifactsDebug" : "SUCCESS", 26 | ":app:dataBindingMergeDependencyArtifactsRelease" : "SUCCESS", 27 | ":app:dataBindingTriggerDebug" : "SUCCESS", 28 | ":app:dataBindingTriggerRelease" : "SUCCESS", 29 | ":app:desugarDebugFileDependencies" : "FROM_CACHE", 30 | ":app:desugarReleaseFileDependencies" : "FROM_CACHE", 31 | ":app:dexBuilderDebug" : "FROM_CACHE", 32 | ":app:dexBuilderRelease" : "FROM_CACHE", 33 | ":app:extractDeepLinksDebug" : "FROM_CACHE", 34 | ":app:extractDeepLinksRelease" : "FROM_CACHE", 35 | ":app:extractReleaseNativeSymbolTables" : "NO_SOURCE", 36 | ":app:extractReleaseVersionControlInfo" : "SUCCESS", 37 | ":app:generateDebugAssets" : "UP_TO_DATE", 38 | ":app:generateDebugResources" : "FROM_CACHE", 39 | ":app:generateDebugResValues" : "FROM_CACHE", 40 | ":app:generateReleaseAssets" : "UP_TO_DATE", 41 | ":app:generateReleaseResources" : "FROM_CACHE", 42 | ":app:generateReleaseResValues" : "FROM_CACHE", 43 | ":app:javaPreCompileDebug" : "FROM_CACHE", 44 | ":app:javaPreCompileRelease" : "FROM_CACHE", 45 | ":app:kaptDebugKotlin" : "FROM_CACHE", 46 | ":app:kaptGenerateStubsDebugKotlin" : "FROM_CACHE", 47 | ":app:kaptGenerateStubsReleaseKotlin" : "FROM_CACHE", 48 | ":app:kaptReleaseKotlin" : "FROM_CACHE", 49 | ":app:mapDebugSourceSetPaths" : "SUCCESS", 50 | ":app:mapReleaseSourceSetPaths" : "SUCCESS", 51 | ":app:mergeDebugAssets" : "SUCCESS", 52 | ":app:mergeDebugGlobalSynthetics" : "FROM_CACHE", 53 | ":app:mergeDebugJavaResource" : "SUCCESS", 54 | ":app:mergeDebugJniLibFolders" : "SUCCESS", 55 | ":app:mergeDebugNativeDebugMetadata" : "NO_SOURCE", 56 | ":app:mergeDebugNativeLibs" : "NO_SOURCE", 57 | ":app:mergeDebugResources" : "FROM_CACHE", 58 | ":app:mergeDebugShaders" : "SUCCESS", 59 | ":app:mergeDexRelease" : "FROM_CACHE", 60 | ":app:mergeExtDexDebug" : "FROM_CACHE", 61 | ":app:mergeExtDexRelease" : "FROM_CACHE", 62 | ":app:mergeLibDexDebug" : "FROM_CACHE", 63 | ":app:mergeProjectDexDebug" : "FROM_CACHE", 64 | ":app:mergeReleaseArtProfile" : "SUCCESS", 65 | ":app:mergeReleaseAssets" : "SUCCESS", 66 | ":app:mergeReleaseGlobalSynthetics" : "FROM_CACHE", 67 | ":app:mergeReleaseJavaResource" : "SUCCESS", 68 | ":app:mergeReleaseJniLibFolders" : "SUCCESS", 69 | ":app:mergeReleaseNativeDebugMetadata" : "NO_SOURCE", 70 | ":app:mergeReleaseNativeLibs" : "NO_SOURCE", 71 | ":app:mergeReleaseResources" : "FROM_CACHE", 72 | ":app:mergeReleaseShaders" : "SUCCESS", 73 | ":app:optimizeReleaseResources" : "FROM_CACHE", 74 | ":app:packageDebug" : "SUCCESS", 75 | ":app:packageDebugResources" : "FROM_CACHE", 76 | ":app:packageReleaseResources" : "FROM_CACHE", 77 | ":app:parseDebugLocalResources" : "FROM_CACHE", 78 | ":app:parseReleaseLocalResources" : "FROM_CACHE", 79 | ":app:packageRelease" : "SUCCESS", 80 | ":app:preBuild" : "UP_TO_DATE", 81 | ":app:preDebugBuild" : "UP_TO_DATE", 82 | ":app:preReleaseBuild" : "UP_TO_DATE", 83 | ":app:processDebugJavaRes" : "SUCCESS", 84 | ":app:processDebugMainManifest" : "FROM_CACHE", 85 | ":app:processDebugManifest" : "FROM_CACHE", 86 | ":app:processDebugManifestForPackage" : "FROM_CACHE", 87 | ":app:processDebugResources" : "FROM_CACHE", 88 | ":app:processReleaseJavaRes" : "SUCCESS", 89 | ":app:processReleaseMainManifest" : "FROM_CACHE", 90 | ":app:processReleaseManifest" : "FROM_CACHE", 91 | ":app:processReleaseManifestForPackage" : "FROM_CACHE", 92 | ":app:processReleaseResources" : "FROM_CACHE", 93 | ":app:sdkReleaseDependencyData" : "SUCCESS", 94 | ":app:stripDebugDebugSymbols" : "NO_SOURCE", 95 | ":app:stripReleaseDebugSymbols" : "NO_SOURCE", 96 | ":app:validateSigningDebug" : "SUCCESS", 97 | ":app:writeDebugAppMetadata" : "SUCCESS", 98 | ":app:writeDebugSigningConfigVersions" : "SUCCESS", 99 | ":app:writeReleaseAppMetadata" : "SUCCESS", 100 | ":app:writeReleaseSigningConfigVersions" : "SUCCESS", 101 | ":app:mergeReleaseStartupProfile" : "SUCCESS", 102 | ":library:assemble" : "SUCCESS", 103 | ":library:assembleDebug" : "SUCCESS", 104 | ":library:assembleRelease" : "SUCCESS", 105 | ":library:bundleDebugAar" : "SUCCESS", 106 | ":library:bundleLibCompileToJarDebug" : "SUCCESS", 107 | ":library:bundleLibCompileToJarRelease" : "SUCCESS", 108 | ":library:bundleLibRuntimeToDirDebug" : "SUCCESS", 109 | ":library:bundleLibRuntimeToDirRelease" : "SUCCESS", 110 | ":library:bundleLibRuntimeToJarDebug" : "SUCCESS", 111 | ":library:bundleLibRuntimeToJarRelease" : "SUCCESS", 112 | ":library:bundleReleaseAar" : "SUCCESS", 113 | ":library:compileDebugJavaWithJavac" : "FROM_CACHE", 114 | ":library:compileDebugKotlin" : "FROM_CACHE", 115 | ":library:compileDebugLibraryResources" : "FROM_CACHE", 116 | ":library:compileDebugShaders" : "NO_SOURCE", 117 | ":library:compileReleaseJavaWithJavac" : "FROM_CACHE", 118 | ":library:compileReleaseKotlin" : "FROM_CACHE", 119 | ":library:compileReleaseLibraryResources" : "FROM_CACHE", 120 | ":library:compileReleaseShaders" : "NO_SOURCE", 121 | ":library:copyDebugJniLibsProjectAndLocalJars" : "SUCCESS", 122 | ":library:copyDebugJniLibsProjectOnly" : "SUCCESS", 123 | ":library:copyReleaseJniLibsProjectAndLocalJars" : "SUCCESS", 124 | ":library:copyReleaseJniLibsProjectOnly" : "SUCCESS", 125 | ":library:createFullJarDebug" : "SUCCESS", 126 | ":library:createFullJarRelease" : "SUCCESS", 127 | ":library:dataBindingGenBaseClassesDebug" : "FROM_CACHE", 128 | ":library:dataBindingGenBaseClassesRelease" : "FROM_CACHE", 129 | ":library:dataBindingMergeDependencyArtifactsDebug" : "SUCCESS", 130 | ":library:dataBindingMergeDependencyArtifactsRelease": "SUCCESS", 131 | ":library:dataBindingTriggerDebug" : "SUCCESS", 132 | ":library:dataBindingTriggerRelease" : "SUCCESS", 133 | ":library:extractDebugAnnotations" : "FROM_CACHE", 134 | ":library:extractDeepLinksDebug" : "FROM_CACHE", 135 | ":library:extractDeepLinksForAarDebug" : "FROM_CACHE", 136 | ":library:extractDeepLinksForAarRelease" : "FROM_CACHE", 137 | ":library:extractDeepLinksRelease" : "FROM_CACHE", 138 | ":library:extractReleaseAnnotations" : "FROM_CACHE", 139 | ":library:generateDebugAssets" : "UP_TO_DATE", 140 | ":library:generateDebugResources" : "FROM_CACHE", 141 | ":library:generateDebugResValues" : "FROM_CACHE", 142 | ":library:generateDebugRFile" : "FROM_CACHE", 143 | ":library:generateReleaseAssets" : "UP_TO_DATE", 144 | ":library:generateReleaseResources" : "FROM_CACHE", 145 | ":library:generateReleaseResValues" : "FROM_CACHE", 146 | ":library:generateReleaseRFile" : "FROM_CACHE", 147 | ":library:javaPreCompileDebug" : "FROM_CACHE", 148 | ":library:javaPreCompileRelease" : "FROM_CACHE", 149 | ":library:kaptDebugKotlin" : "FROM_CACHE", 150 | ":library:kaptGenerateStubsDebugKotlin" : "FROM_CACHE", 151 | ":library:kaptGenerateStubsReleaseKotlin" : "FROM_CACHE", 152 | ":library:kaptReleaseKotlin" : "FROM_CACHE", 153 | ":library:mapReleaseSourceSetPaths" : "SUCCESS", 154 | ":library:mergeDebugAssets" : "SUCCESS", 155 | ":library:mergeDebugConsumerProguardFiles" : "SUCCESS", 156 | ":library:mergeDebugGeneratedProguardFiles" : "SUCCESS", 157 | ":library:mergeDebugJavaResource" : "SUCCESS", 158 | ":library:mergeDebugJniLibFolders" : "SUCCESS", 159 | ":library:mergeDebugNativeLibs" : "NO_SOURCE", 160 | ":library:mergeDebugShaders" : "SUCCESS", 161 | ":library:mergeReleaseAssets" : "SUCCESS", 162 | ":library:mergeReleaseConsumerProguardFiles" : "SUCCESS", 163 | ":library:mergeReleaseGeneratedProguardFiles" : "SUCCESS", 164 | ":library:mergeReleaseJavaResource" : "SUCCESS", 165 | ":library:mergeReleaseJniLibFolders" : "SUCCESS", 166 | ":library:mergeReleaseNativeLibs" : "NO_SOURCE", 167 | ":library:mergeReleaseResources" : "FROM_CACHE", 168 | ":library:mergeReleaseShaders" : "SUCCESS", 169 | ":library:packageDebugResources" : "FROM_CACHE", 170 | ":library:packageReleaseResources" : "FROM_CACHE", 171 | ":library:parseDebugLocalResources" : "FROM_CACHE", 172 | ":library:parseReleaseLocalResources" : "FROM_CACHE", 173 | ":library:preBuild" : "UP_TO_DATE", 174 | ":library:preDebugBuild" : "UP_TO_DATE", 175 | ":library:prepareDebugArtProfile" : "SUCCESS", 176 | ":library:prepareLintJarForPublish" : "SUCCESS", 177 | ":library:prepareReleaseArtProfile" : "SUCCESS", 178 | ":library:preReleaseBuild" : "UP_TO_DATE", 179 | ":library:processDebugJavaRes" : "SUCCESS", 180 | ":library:processDebugManifest" : "FROM_CACHE", 181 | ":library:processReleaseJavaRes" : "SUCCESS", 182 | ":library:processReleaseManifest" : "FROM_CACHE", 183 | ":library:stripDebugDebugSymbols" : "NO_SOURCE", 184 | ":library:stripReleaseDebugSymbols" : "NO_SOURCE", 185 | ":library:syncDebugLibJars" : "FROM_CACHE", 186 | ":library:syncReleaseLibJars" : "FROM_CACHE", 187 | ":library:verifyReleaseResources" : "FROM_CACHE", 188 | ":library:writeDebugAarMetadata" : "SUCCESS", 189 | ":library:writeReleaseAarMetadata" : "SUCCESS", 190 | ":app:checkKotlinGradlePluginConfigurationErrors" : "SKIPPED", 191 | ":library:checkKotlinGradlePluginConfigurationErrors": "SKIPPED" 192 | } 193 | -------------------------------------------------------------------------------- /src/test/resources/expectedOutcomes/8.1_outcomes.json: -------------------------------------------------------------------------------- 1 | { 2 | ":app:assemble" : "SUCCESS", 3 | ":app:assembleDebug" : "SUCCESS", 4 | ":app:assembleRelease" : "SUCCESS", 5 | ":app:checkDebugAarMetadata" : "SUCCESS", 6 | ":app:checkDebugDuplicateClasses" : "SUCCESS", 7 | ":app:checkReleaseAarMetadata" : "SUCCESS", 8 | ":app:checkReleaseDuplicateClasses" : "SUCCESS", 9 | ":app:collectReleaseDependencies" : "SUCCESS", 10 | ":app:compileDebugJavaWithJavac" : "FROM_CACHE", 11 | ":app:compileDebugKotlin" : "FROM_CACHE", 12 | ":app:compileDebugShaders" : "NO_SOURCE", 13 | ":app:compileReleaseArtProfile" : "FROM_CACHE", 14 | ":app:compileReleaseJavaWithJavac" : "FROM_CACHE", 15 | ":app:compileReleaseKotlin" : "FROM_CACHE", 16 | ":app:compileReleaseShaders" : "NO_SOURCE", 17 | ":app:compressDebugAssets" : "FROM_CACHE", 18 | ":app:compressReleaseAssets" : "FROM_CACHE", 19 | ":app:createDebugApkListingFileRedirect" : "SUCCESS", 20 | ":app:createDebugCompatibleScreenManifests" : "SUCCESS", 21 | ":app:createReleaseApkListingFileRedirect" : "SUCCESS", 22 | ":app:createReleaseCompatibleScreenManifests" : "SUCCESS", 23 | ":app:dataBindingGenBaseClassesDebug" : "FROM_CACHE", 24 | ":app:dataBindingGenBaseClassesRelease" : "FROM_CACHE", 25 | ":app:dataBindingMergeDependencyArtifactsDebug" : "SUCCESS", 26 | ":app:dataBindingMergeDependencyArtifactsRelease" : "SUCCESS", 27 | ":app:dataBindingTriggerDebug" : "SUCCESS", 28 | ":app:dataBindingTriggerRelease" : "SUCCESS", 29 | ":app:desugarDebugFileDependencies" : "FROM_CACHE", 30 | ":app:desugarReleaseFileDependencies" : "FROM_CACHE", 31 | ":app:dexBuilderDebug" : "FROM_CACHE", 32 | ":app:dexBuilderRelease" : "FROM_CACHE", 33 | ":app:extractDeepLinksDebug" : "FROM_CACHE", 34 | ":app:extractDeepLinksRelease" : "FROM_CACHE", 35 | ":app:extractReleaseNativeSymbolTables" : "NO_SOURCE", 36 | ":app:generateDebugAssets" : "UP_TO_DATE", 37 | ":app:generateDebugResources" : "UP_TO_DATE", 38 | ":app:generateDebugResValues" : "FROM_CACHE", 39 | ":app:generateReleaseAssets" : "UP_TO_DATE", 40 | ":app:generateReleaseResources" : "UP_TO_DATE", 41 | ":app:generateReleaseResValues" : "FROM_CACHE", 42 | ":app:javaPreCompileDebug" : "FROM_CACHE", 43 | ":app:javaPreCompileRelease" : "FROM_CACHE", 44 | ":app:kaptDebugKotlin" : "FROM_CACHE", 45 | ":app:kaptGenerateStubsDebugKotlin" : "FROM_CACHE", 46 | ":app:kaptGenerateStubsReleaseKotlin" : "FROM_CACHE", 47 | ":app:kaptReleaseKotlin" : "FROM_CACHE", 48 | ":app:mapDebugSourceSetPaths" : "SUCCESS", 49 | ":app:mapReleaseSourceSetPaths" : "SUCCESS", 50 | ":app:mergeDebugAssets" : "SUCCESS", 51 | ":app:mergeDebugGlobalSynthetics" : "FROM_CACHE", 52 | ":app:mergeDebugJavaResource" : "SUCCESS", 53 | ":app:mergeDebugJniLibFolders" : "SUCCESS", 54 | ":app:mergeDebugNativeDebugMetadata" : "NO_SOURCE", 55 | ":app:mergeDebugNativeLibs" : "NO_SOURCE", 56 | ":app:mergeDebugResources" : "FROM_CACHE", 57 | ":app:mergeDebugShaders" : "SUCCESS", 58 | ":app:mergeDexRelease" : "FROM_CACHE", 59 | ":app:mergeExtDexDebug" : "FROM_CACHE", 60 | ":app:mergeExtDexRelease" : "FROM_CACHE", 61 | ":app:mergeLibDexDebug" : "FROM_CACHE", 62 | ":app:mergeProjectDexDebug" : "FROM_CACHE", 63 | ":app:mergeReleaseArtProfile" : "SUCCESS", 64 | ":app:mergeReleaseAssets" : "SUCCESS", 65 | ":app:mergeReleaseGlobalSynthetics" : "FROM_CACHE", 66 | ":app:mergeReleaseJavaResource" : "SUCCESS", 67 | ":app:mergeReleaseJniLibFolders" : "SUCCESS", 68 | ":app:mergeReleaseNativeDebugMetadata" : "NO_SOURCE", 69 | ":app:mergeReleaseNativeLibs" : "NO_SOURCE", 70 | ":app:mergeReleaseResources" : "FROM_CACHE", 71 | ":app:mergeReleaseShaders" : "SUCCESS", 72 | ":app:optimizeReleaseResources" : "FROM_CACHE", 73 | ":app:packageDebug" : "SUCCESS", 74 | ":app:packageDebugResources" : "FROM_CACHE", 75 | ":app:packageReleaseResources" : "FROM_CACHE", 76 | ":app:parseDebugLocalResources" : "FROM_CACHE", 77 | ":app:parseReleaseLocalResources" : "FROM_CACHE", 78 | ":app:packageRelease" : "SUCCESS", 79 | ":app:preBuild" : "UP_TO_DATE", 80 | ":app:preDebugBuild" : "UP_TO_DATE", 81 | ":app:preReleaseBuild" : "UP_TO_DATE", 82 | ":app:processDebugJavaRes" : "SUCCESS", 83 | ":app:processDebugMainManifest" : "FROM_CACHE", 84 | ":app:processDebugManifest" : "FROM_CACHE", 85 | ":app:processDebugManifestForPackage" : "FROM_CACHE", 86 | ":app:processDebugResources" : "FROM_CACHE", 87 | ":app:processReleaseJavaRes" : "SUCCESS", 88 | ":app:processReleaseMainManifest" : "FROM_CACHE", 89 | ":app:processReleaseManifest" : "FROM_CACHE", 90 | ":app:processReleaseManifestForPackage" : "FROM_CACHE", 91 | ":app:processReleaseResources" : "FROM_CACHE", 92 | ":app:sdkReleaseDependencyData" : "SUCCESS", 93 | ":app:stripDebugDebugSymbols" : "NO_SOURCE", 94 | ":app:stripReleaseDebugSymbols" : "NO_SOURCE", 95 | ":app:validateSigningDebug" : "SUCCESS", 96 | ":app:writeDebugAppMetadata" : "SUCCESS", 97 | ":app:writeDebugSigningConfigVersions" : "SUCCESS", 98 | ":app:writeReleaseAppMetadata" : "SUCCESS", 99 | ":app:writeReleaseSigningConfigVersions" : "SUCCESS", 100 | ":library:assemble" : "SUCCESS", 101 | ":library:assembleDebug" : "SUCCESS", 102 | ":library:assembleRelease" : "SUCCESS", 103 | ":library:bundleDebugAar" : "SUCCESS", 104 | ":library:bundleLibCompileToJarDebug" : "SUCCESS", 105 | ":library:bundleLibCompileToJarRelease" : "SUCCESS", 106 | ":library:bundleLibRuntimeToDirDebug" : "SUCCESS", 107 | ":library:bundleLibRuntimeToDirRelease" : "SUCCESS", 108 | ":library:bundleLibRuntimeToJarDebug" : "SUCCESS", 109 | ":library:bundleLibRuntimeToJarRelease" : "SUCCESS", 110 | ":library:bundleReleaseAar" : "SUCCESS", 111 | ":library:compileDebugJavaWithJavac" : "FROM_CACHE", 112 | ":library:compileDebugKotlin" : "FROM_CACHE", 113 | ":library:compileDebugLibraryResources" : "FROM_CACHE", 114 | ":library:compileDebugShaders" : "NO_SOURCE", 115 | ":library:compileReleaseJavaWithJavac" : "FROM_CACHE", 116 | ":library:compileReleaseKotlin" : "FROM_CACHE", 117 | ":library:compileReleaseLibraryResources" : "FROM_CACHE", 118 | ":library:compileReleaseShaders" : "NO_SOURCE", 119 | ":library:copyDebugJniLibsProjectAndLocalJars" : "SUCCESS", 120 | ":library:copyDebugJniLibsProjectOnly" : "SUCCESS", 121 | ":library:copyReleaseJniLibsProjectAndLocalJars" : "SUCCESS", 122 | ":library:copyReleaseJniLibsProjectOnly" : "SUCCESS", 123 | ":library:createFullJarDebug" : "SUCCESS", 124 | ":library:createFullJarRelease" : "SUCCESS", 125 | ":library:dataBindingGenBaseClassesDebug" : "FROM_CACHE", 126 | ":library:dataBindingGenBaseClassesRelease" : "FROM_CACHE", 127 | ":library:dataBindingMergeDependencyArtifactsDebug" : "SUCCESS", 128 | ":library:dataBindingMergeDependencyArtifactsRelease": "SUCCESS", 129 | ":library:dataBindingTriggerDebug" : "SUCCESS", 130 | ":library:dataBindingTriggerRelease" : "SUCCESS", 131 | ":library:extractDebugAnnotations" : "FROM_CACHE", 132 | ":library:extractDeepLinksDebug" : "FROM_CACHE", 133 | ":library:extractDeepLinksForAarDebug" : "FROM_CACHE", 134 | ":library:extractDeepLinksForAarRelease" : "FROM_CACHE", 135 | ":library:extractDeepLinksRelease" : "FROM_CACHE", 136 | ":library:extractReleaseAnnotations" : "FROM_CACHE", 137 | ":library:generateDebugAssets" : "UP_TO_DATE", 138 | ":library:generateDebugResources" : "UP_TO_DATE", 139 | ":library:generateDebugResValues" : "FROM_CACHE", 140 | ":library:generateDebugRFile" : "FROM_CACHE", 141 | ":library:generateReleaseAssets" : "UP_TO_DATE", 142 | ":library:generateReleaseResources" : "UP_TO_DATE", 143 | ":library:generateReleaseResValues" : "FROM_CACHE", 144 | ":library:generateReleaseRFile" : "FROM_CACHE", 145 | ":library:javaPreCompileDebug" : "FROM_CACHE", 146 | ":library:javaPreCompileRelease" : "FROM_CACHE", 147 | ":library:kaptDebugKotlin" : "FROM_CACHE", 148 | ":library:kaptGenerateStubsDebugKotlin" : "FROM_CACHE", 149 | ":library:kaptGenerateStubsReleaseKotlin" : "FROM_CACHE", 150 | ":library:kaptReleaseKotlin" : "FROM_CACHE", 151 | ":library:mapReleaseSourceSetPaths" : "SUCCESS", 152 | ":library:mergeDebugConsumerProguardFiles" : "SUCCESS", 153 | ":library:mergeDebugGeneratedProguardFiles" : "SUCCESS", 154 | ":library:mergeDebugJavaResource" : "SUCCESS", 155 | ":library:mergeDebugJniLibFolders" : "SUCCESS", 156 | ":library:mergeDebugNativeLibs" : "NO_SOURCE", 157 | ":library:mergeDebugShaders" : "SUCCESS", 158 | ":library:mergeReleaseConsumerProguardFiles" : "SUCCESS", 159 | ":library:mergeReleaseGeneratedProguardFiles" : "SUCCESS", 160 | ":library:mergeReleaseJavaResource" : "SUCCESS", 161 | ":library:mergeReleaseJniLibFolders" : "SUCCESS", 162 | ":library:mergeReleaseNativeLibs" : "NO_SOURCE", 163 | ":library:mergeReleaseResources" : "FROM_CACHE", 164 | ":library:mergeReleaseShaders" : "SUCCESS", 165 | ":library:packageDebugAssets" : "SUCCESS", 166 | ":library:packageDebugResources" : "FROM_CACHE", 167 | ":library:packageReleaseAssets" : "SUCCESS", 168 | ":library:packageReleaseResources" : "FROM_CACHE", 169 | ":library:parseDebugLocalResources" : "FROM_CACHE", 170 | ":library:parseReleaseLocalResources" : "FROM_CACHE", 171 | ":library:preBuild" : "UP_TO_DATE", 172 | ":library:preDebugBuild" : "UP_TO_DATE", 173 | ":library:prepareDebugArtProfile" : "SUCCESS", 174 | ":library:prepareLintJarForPublish" : "SUCCESS", 175 | ":library:prepareReleaseArtProfile" : "SUCCESS", 176 | ":library:preReleaseBuild" : "UP_TO_DATE", 177 | ":library:processDebugJavaRes" : "SUCCESS", 178 | ":library:processDebugManifest" : "FROM_CACHE", 179 | ":library:processReleaseJavaRes" : "SUCCESS", 180 | ":library:processReleaseManifest" : "FROM_CACHE", 181 | ":library:stripDebugDebugSymbols" : "NO_SOURCE", 182 | ":library:stripReleaseDebugSymbols" : "NO_SOURCE", 183 | ":library:syncDebugLibJars" : "FROM_CACHE", 184 | ":library:syncReleaseLibJars" : "FROM_CACHE", 185 | ":library:verifyReleaseResources" : "FROM_CACHE", 186 | ":library:writeDebugAarMetadata" : "SUCCESS", 187 | ":library:writeReleaseAarMetadata" : "SUCCESS", 188 | ":app:checkKotlinGradlePluginConfigurationErrors" : "SKIPPED", 189 | ":library:checkKotlinGradlePluginConfigurationErrors": "SKIPPED" 190 | } 191 | -------------------------------------------------------------------------------- /src/test/resources/expectedOutcomes/8.2_outcomes.json: -------------------------------------------------------------------------------- 1 | { 2 | ":app:assemble" : "SUCCESS", 3 | ":app:assembleDebug" : "SUCCESS", 4 | ":app:assembleRelease" : "SUCCESS", 5 | ":app:checkDebugAarMetadata" : "SUCCESS", 6 | ":app:checkDebugDuplicateClasses" : "SUCCESS", 7 | ":app:checkReleaseAarMetadata" : "SUCCESS", 8 | ":app:checkReleaseDuplicateClasses" : "SUCCESS", 9 | ":app:collectReleaseDependencies" : "SUCCESS", 10 | ":app:compileDebugJavaWithJavac" : "FROM_CACHE", 11 | ":app:compileDebugKotlin" : "FROM_CACHE", 12 | ":app:compileDebugShaders" : "NO_SOURCE", 13 | ":app:compileReleaseArtProfile" : "FROM_CACHE", 14 | ":app:compileReleaseJavaWithJavac" : "FROM_CACHE", 15 | ":app:compileReleaseKotlin" : "FROM_CACHE", 16 | ":app:compileReleaseShaders" : "NO_SOURCE", 17 | ":app:compressDebugAssets" : "FROM_CACHE", 18 | ":app:compressReleaseAssets" : "FROM_CACHE", 19 | ":app:createDebugApkListingFileRedirect" : "SUCCESS", 20 | ":app:createDebugCompatibleScreenManifests" : "SUCCESS", 21 | ":app:createReleaseApkListingFileRedirect" : "SUCCESS", 22 | ":app:createReleaseCompatibleScreenManifests" : "SUCCESS", 23 | ":app:dataBindingGenBaseClassesDebug" : "FROM_CACHE", 24 | ":app:dataBindingGenBaseClassesRelease" : "FROM_CACHE", 25 | ":app:dataBindingMergeDependencyArtifactsDebug" : "SUCCESS", 26 | ":app:dataBindingMergeDependencyArtifactsRelease" : "SUCCESS", 27 | ":app:dataBindingTriggerDebug" : "SUCCESS", 28 | ":app:dataBindingTriggerRelease" : "SUCCESS", 29 | ":app:desugarDebugFileDependencies" : "FROM_CACHE", 30 | ":app:desugarReleaseFileDependencies" : "FROM_CACHE", 31 | ":app:dexBuilderDebug" : "FROM_CACHE", 32 | ":app:dexBuilderRelease" : "FROM_CACHE", 33 | ":app:extractDeepLinksDebug" : "FROM_CACHE", 34 | ":app:extractDeepLinksRelease" : "FROM_CACHE", 35 | ":app:extractReleaseNativeSymbolTables" : "NO_SOURCE", 36 | ":app:generateDebugAssets" : "UP_TO_DATE", 37 | ":app:generateDebugResources" : "UP_TO_DATE", 38 | ":app:generateDebugResValues" : "FROM_CACHE", 39 | ":app:generateReleaseAssets" : "UP_TO_DATE", 40 | ":app:generateReleaseResources" : "UP_TO_DATE", 41 | ":app:generateReleaseResValues" : "FROM_CACHE", 42 | ":app:javaPreCompileDebug" : "FROM_CACHE", 43 | ":app:javaPreCompileRelease" : "FROM_CACHE", 44 | ":app:kaptDebugKotlin" : "FROM_CACHE", 45 | ":app:kaptGenerateStubsDebugKotlin" : "FROM_CACHE", 46 | ":app:kaptGenerateStubsReleaseKotlin" : "FROM_CACHE", 47 | ":app:kaptReleaseKotlin" : "FROM_CACHE", 48 | ":app:mapDebugSourceSetPaths" : "SUCCESS", 49 | ":app:mapReleaseSourceSetPaths" : "SUCCESS", 50 | ":app:mergeDebugAssets" : "SUCCESS", 51 | ":app:mergeDebugGlobalSynthetics" : "FROM_CACHE", 52 | ":app:mergeDebugJavaResource" : "SUCCESS", 53 | ":app:mergeDebugJniLibFolders" : "SUCCESS", 54 | ":app:mergeDebugNativeDebugMetadata" : "NO_SOURCE", 55 | ":app:mergeDebugNativeLibs" : "NO_SOURCE", 56 | ":app:mergeDebugResources" : "FROM_CACHE", 57 | ":app:mergeDebugShaders" : "SUCCESS", 58 | ":app:mergeDexRelease" : "FROM_CACHE", 59 | ":app:mergeExtDexDebug" : "FROM_CACHE", 60 | ":app:mergeExtDexRelease" : "FROM_CACHE", 61 | ":app:mergeLibDexDebug" : "FROM_CACHE", 62 | ":app:mergeProjectDexDebug" : "FROM_CACHE", 63 | ":app:mergeReleaseArtProfile" : "SUCCESS", 64 | ":app:mergeReleaseAssets" : "SUCCESS", 65 | ":app:mergeReleaseGlobalSynthetics" : "FROM_CACHE", 66 | ":app:mergeReleaseJavaResource" : "SUCCESS", 67 | ":app:mergeReleaseJniLibFolders" : "SUCCESS", 68 | ":app:mergeReleaseNativeDebugMetadata" : "NO_SOURCE", 69 | ":app:mergeReleaseNativeLibs" : "NO_SOURCE", 70 | ":app:mergeReleaseResources" : "FROM_CACHE", 71 | ":app:mergeReleaseShaders" : "SUCCESS", 72 | ":app:optimizeReleaseResources" : "FROM_CACHE", 73 | ":app:packageDebug" : "SUCCESS", 74 | ":app:packageDebugResources" : "FROM_CACHE", 75 | ":app:packageReleaseResources" : "FROM_CACHE", 76 | ":app:parseDebugLocalResources" : "FROM_CACHE", 77 | ":app:parseReleaseLocalResources" : "FROM_CACHE", 78 | ":app:packageRelease" : "SUCCESS", 79 | ":app:preBuild" : "UP_TO_DATE", 80 | ":app:preDebugBuild" : "UP_TO_DATE", 81 | ":app:preReleaseBuild" : "UP_TO_DATE", 82 | ":app:processDebugJavaRes" : "SUCCESS", 83 | ":app:processDebugMainManifest" : "FROM_CACHE", 84 | ":app:processDebugManifest" : "FROM_CACHE", 85 | ":app:processDebugManifestForPackage" : "FROM_CACHE", 86 | ":app:processDebugResources" : "FROM_CACHE", 87 | ":app:processReleaseJavaRes" : "SUCCESS", 88 | ":app:processReleaseMainManifest" : "FROM_CACHE", 89 | ":app:processReleaseManifest" : "FROM_CACHE", 90 | ":app:processReleaseManifestForPackage" : "FROM_CACHE", 91 | ":app:processReleaseResources" : "FROM_CACHE", 92 | ":app:sdkReleaseDependencyData" : "SUCCESS", 93 | ":app:stripDebugDebugSymbols" : "NO_SOURCE", 94 | ":app:stripReleaseDebugSymbols" : "NO_SOURCE", 95 | ":app:validateSigningDebug" : "SUCCESS", 96 | ":app:writeDebugAppMetadata" : "SUCCESS", 97 | ":app:writeDebugSigningConfigVersions" : "SUCCESS", 98 | ":app:writeReleaseAppMetadata" : "SUCCESS", 99 | ":app:writeReleaseSigningConfigVersions" : "SUCCESS", 100 | ":library:assemble" : "SUCCESS", 101 | ":library:assembleDebug" : "SUCCESS", 102 | ":library:assembleRelease" : "SUCCESS", 103 | ":library:bundleDebugAar" : "SUCCESS", 104 | ":library:bundleLibCompileToJarDebug" : "SUCCESS", 105 | ":library:bundleLibCompileToJarRelease" : "SUCCESS", 106 | ":library:bundleLibRuntimeToDirDebug" : "SUCCESS", 107 | ":library:bundleLibRuntimeToDirRelease" : "SUCCESS", 108 | ":library:bundleLibRuntimeToJarDebug" : "SUCCESS", 109 | ":library:bundleLibRuntimeToJarRelease" : "SUCCESS", 110 | ":library:bundleReleaseAar" : "SUCCESS", 111 | ":library:compileDebugJavaWithJavac" : "FROM_CACHE", 112 | ":library:compileDebugKotlin" : "FROM_CACHE", 113 | ":library:compileDebugLibraryResources" : "FROM_CACHE", 114 | ":library:compileDebugShaders" : "NO_SOURCE", 115 | ":library:compileReleaseJavaWithJavac" : "FROM_CACHE", 116 | ":library:compileReleaseKotlin" : "FROM_CACHE", 117 | ":library:compileReleaseLibraryResources" : "FROM_CACHE", 118 | ":library:compileReleaseShaders" : "NO_SOURCE", 119 | ":library:copyDebugJniLibsProjectAndLocalJars" : "SUCCESS", 120 | ":library:copyDebugJniLibsProjectOnly" : "SUCCESS", 121 | ":library:copyReleaseJniLibsProjectAndLocalJars" : "SUCCESS", 122 | ":library:copyReleaseJniLibsProjectOnly" : "SUCCESS", 123 | ":library:createFullJarDebug" : "SUCCESS", 124 | ":library:createFullJarRelease" : "SUCCESS", 125 | ":library:dataBindingGenBaseClassesDebug" : "FROM_CACHE", 126 | ":library:dataBindingGenBaseClassesRelease" : "FROM_CACHE", 127 | ":library:dataBindingMergeDependencyArtifactsDebug" : "SUCCESS", 128 | ":library:dataBindingMergeDependencyArtifactsRelease": "SUCCESS", 129 | ":library:dataBindingTriggerDebug" : "SUCCESS", 130 | ":library:dataBindingTriggerRelease" : "SUCCESS", 131 | ":library:extractDebugAnnotations" : "FROM_CACHE", 132 | ":library:extractDeepLinksDebug" : "FROM_CACHE", 133 | ":library:extractDeepLinksForAarDebug" : "FROM_CACHE", 134 | ":library:extractDeepLinksForAarRelease" : "FROM_CACHE", 135 | ":library:extractDeepLinksRelease" : "FROM_CACHE", 136 | ":library:extractReleaseAnnotations" : "FROM_CACHE", 137 | ":library:generateDebugAssets" : "UP_TO_DATE", 138 | ":library:generateDebugResources" : "UP_TO_DATE", 139 | ":library:generateDebugResValues" : "FROM_CACHE", 140 | ":library:generateDebugRFile" : "FROM_CACHE", 141 | ":library:generateReleaseAssets" : "UP_TO_DATE", 142 | ":library:generateReleaseResources" : "UP_TO_DATE", 143 | ":library:generateReleaseResValues" : "FROM_CACHE", 144 | ":library:generateReleaseRFile" : "FROM_CACHE", 145 | ":library:javaPreCompileDebug" : "FROM_CACHE", 146 | ":library:javaPreCompileRelease" : "FROM_CACHE", 147 | ":library:kaptDebugKotlin" : "FROM_CACHE", 148 | ":library:kaptGenerateStubsDebugKotlin" : "FROM_CACHE", 149 | ":library:kaptGenerateStubsReleaseKotlin" : "FROM_CACHE", 150 | ":library:kaptReleaseKotlin" : "FROM_CACHE", 151 | ":library:mapReleaseSourceSetPaths" : "SUCCESS", 152 | ":library:mergeDebugConsumerProguardFiles" : "SUCCESS", 153 | ":library:mergeDebugGeneratedProguardFiles" : "SUCCESS", 154 | ":library:mergeDebugJavaResource" : "SUCCESS", 155 | ":library:mergeDebugJniLibFolders" : "SUCCESS", 156 | ":library:mergeDebugNativeLibs" : "NO_SOURCE", 157 | ":library:mergeDebugShaders" : "SUCCESS", 158 | ":library:mergeReleaseConsumerProguardFiles" : "SUCCESS", 159 | ":library:mergeReleaseGeneratedProguardFiles" : "SUCCESS", 160 | ":library:mergeReleaseJavaResource" : "SUCCESS", 161 | ":library:mergeReleaseJniLibFolders" : "SUCCESS", 162 | ":library:mergeReleaseNativeLibs" : "NO_SOURCE", 163 | ":library:mergeReleaseResources" : "FROM_CACHE", 164 | ":library:mergeReleaseShaders" : "SUCCESS", 165 | ":library:packageDebugAssets" : "SUCCESS", 166 | ":library:packageDebugResources" : "FROM_CACHE", 167 | ":library:packageReleaseAssets" : "SUCCESS", 168 | ":library:packageReleaseResources" : "FROM_CACHE", 169 | ":library:parseDebugLocalResources" : "FROM_CACHE", 170 | ":library:parseReleaseLocalResources" : "FROM_CACHE", 171 | ":library:preBuild" : "UP_TO_DATE", 172 | ":library:preDebugBuild" : "UP_TO_DATE", 173 | ":library:prepareDebugArtProfile" : "SUCCESS", 174 | ":library:prepareLintJarForPublish" : "SUCCESS", 175 | ":library:prepareReleaseArtProfile" : "SUCCESS", 176 | ":library:preReleaseBuild" : "UP_TO_DATE", 177 | ":library:processDebugJavaRes" : "SUCCESS", 178 | ":library:processDebugManifest" : "FROM_CACHE", 179 | ":library:processReleaseJavaRes" : "SUCCESS", 180 | ":library:processReleaseManifest" : "FROM_CACHE", 181 | ":library:stripDebugDebugSymbols" : "NO_SOURCE", 182 | ":library:stripReleaseDebugSymbols" : "NO_SOURCE", 183 | ":library:syncDebugLibJars" : "FROM_CACHE", 184 | ":library:syncReleaseLibJars" : "FROM_CACHE", 185 | ":library:verifyReleaseResources" : "FROM_CACHE", 186 | ":library:writeDebugAarMetadata" : "SUCCESS", 187 | ":library:writeReleaseAarMetadata" : "SUCCESS", 188 | ":app:checkKotlinGradlePluginConfigurationErrors" : "SKIPPED", 189 | ":library:checkKotlinGradlePluginConfigurationErrors": "SKIPPED" 190 | } 191 | -------------------------------------------------------------------------------- /src/test/resources/expectedOutcomes/8.3_outcomes.json: -------------------------------------------------------------------------------- 1 | { 2 | ":app:assemble" : "SUCCESS", 3 | ":app:assembleDebug" : "SUCCESS", 4 | ":app:assembleRelease" : "SUCCESS", 5 | ":app:checkDebugAarMetadata" : "SUCCESS", 6 | ":app:checkDebugDuplicateClasses" : "SUCCESS", 7 | ":app:checkReleaseAarMetadata" : "SUCCESS", 8 | ":app:checkReleaseDuplicateClasses" : "SUCCESS", 9 | ":app:collectReleaseDependencies" : "SUCCESS", 10 | ":app:compileDebugJavaWithJavac" : "FROM_CACHE", 11 | ":app:compileDebugKotlin" : "FROM_CACHE", 12 | ":app:compileDebugShaders" : "NO_SOURCE", 13 | ":app:compileReleaseArtProfile" : "FROM_CACHE", 14 | ":app:compileReleaseJavaWithJavac" : "FROM_CACHE", 15 | ":app:compileReleaseKotlin" : "FROM_CACHE", 16 | ":app:compileReleaseShaders" : "NO_SOURCE", 17 | ":app:compressDebugAssets" : "FROM_CACHE", 18 | ":app:compressReleaseAssets" : "FROM_CACHE", 19 | ":app:createDebugApkListingFileRedirect" : "SUCCESS", 20 | ":app:createDebugCompatibleScreenManifests" : "SUCCESS", 21 | ":app:createReleaseApkListingFileRedirect" : "SUCCESS", 22 | ":app:createReleaseCompatibleScreenManifests" : "SUCCESS", 23 | ":app:dataBindingGenBaseClassesDebug" : "FROM_CACHE", 24 | ":app:dataBindingGenBaseClassesRelease" : "FROM_CACHE", 25 | ":app:dataBindingMergeDependencyArtifactsDebug" : "SUCCESS", 26 | ":app:dataBindingMergeDependencyArtifactsRelease" : "SUCCESS", 27 | ":app:dataBindingTriggerDebug" : "SUCCESS", 28 | ":app:dataBindingTriggerRelease" : "SUCCESS", 29 | ":app:desugarDebugFileDependencies" : "FROM_CACHE", 30 | ":app:desugarReleaseFileDependencies" : "FROM_CACHE", 31 | ":app:dexBuilderDebug" : "FROM_CACHE", 32 | ":app:dexBuilderRelease" : "FROM_CACHE", 33 | ":app:extractDeepLinksDebug" : "FROM_CACHE", 34 | ":app:extractDeepLinksRelease" : "FROM_CACHE", 35 | ":app:extractReleaseNativeSymbolTables" : "NO_SOURCE", 36 | ":app:extractReleaseVersionControlInfo" : "SUCCESS", 37 | ":app:generateDebugAssets" : "UP_TO_DATE", 38 | ":app:generateDebugResources" : "FROM_CACHE", 39 | ":app:generateDebugResValues" : "FROM_CACHE", 40 | ":app:generateReleaseAssets" : "UP_TO_DATE", 41 | ":app:generateReleaseResources" : "FROM_CACHE", 42 | ":app:generateReleaseResValues" : "FROM_CACHE", 43 | ":app:javaPreCompileDebug" : "FROM_CACHE", 44 | ":app:javaPreCompileRelease" : "FROM_CACHE", 45 | ":app:kaptDebugKotlin" : "FROM_CACHE", 46 | ":app:kaptGenerateStubsDebugKotlin" : "FROM_CACHE", 47 | ":app:kaptGenerateStubsReleaseKotlin" : "FROM_CACHE", 48 | ":app:kaptReleaseKotlin" : "FROM_CACHE", 49 | ":app:mapDebugSourceSetPaths" : "SUCCESS", 50 | ":app:mapReleaseSourceSetPaths" : "SUCCESS", 51 | ":app:mergeDebugAssets" : "SUCCESS", 52 | ":app:mergeDebugGlobalSynthetics" : "FROM_CACHE", 53 | ":app:mergeDebugJavaResource" : "SUCCESS", 54 | ":app:mergeDebugJniLibFolders" : "SUCCESS", 55 | ":app:mergeDebugNativeDebugMetadata" : "NO_SOURCE", 56 | ":app:mergeDebugNativeLibs" : "NO_SOURCE", 57 | ":app:mergeDebugResources" : "FROM_CACHE", 58 | ":app:mergeDebugShaders" : "SUCCESS", 59 | ":app:mergeDexRelease" : "FROM_CACHE", 60 | ":app:mergeExtDexDebug" : "FROM_CACHE", 61 | ":app:mergeExtDexRelease" : "FROM_CACHE", 62 | ":app:mergeLibDexDebug" : "FROM_CACHE", 63 | ":app:mergeProjectDexDebug" : "FROM_CACHE", 64 | ":app:mergeReleaseArtProfile" : "SUCCESS", 65 | ":app:mergeReleaseAssets" : "SUCCESS", 66 | ":app:mergeReleaseGlobalSynthetics" : "FROM_CACHE", 67 | ":app:mergeReleaseJavaResource" : "SUCCESS", 68 | ":app:mergeReleaseJniLibFolders" : "SUCCESS", 69 | ":app:mergeReleaseNativeDebugMetadata" : "NO_SOURCE", 70 | ":app:mergeReleaseNativeLibs" : "NO_SOURCE", 71 | ":app:mergeReleaseResources" : "FROM_CACHE", 72 | ":app:mergeReleaseShaders" : "SUCCESS", 73 | ":app:optimizeReleaseResources" : "FROM_CACHE", 74 | ":app:packageDebug" : "SUCCESS", 75 | ":app:packageDebugResources" : "FROM_CACHE", 76 | ":app:packageReleaseResources" : "FROM_CACHE", 77 | ":app:parseDebugLocalResources" : "FROM_CACHE", 78 | ":app:parseReleaseLocalResources" : "FROM_CACHE", 79 | ":app:packageRelease" : "SUCCESS", 80 | ":app:preBuild" : "UP_TO_DATE", 81 | ":app:preDebugBuild" : "UP_TO_DATE", 82 | ":app:preReleaseBuild" : "UP_TO_DATE", 83 | ":app:processDebugJavaRes" : "SUCCESS", 84 | ":app:processDebugMainManifest" : "FROM_CACHE", 85 | ":app:processDebugManifest" : "FROM_CACHE", 86 | ":app:processDebugManifestForPackage" : "FROM_CACHE", 87 | ":app:processDebugResources" : "FROM_CACHE", 88 | ":app:processReleaseJavaRes" : "SUCCESS", 89 | ":app:processReleaseMainManifest" : "FROM_CACHE", 90 | ":app:processReleaseManifest" : "FROM_CACHE", 91 | ":app:processReleaseManifestForPackage" : "FROM_CACHE", 92 | ":app:processReleaseResources" : "FROM_CACHE", 93 | ":app:sdkReleaseDependencyData" : "SUCCESS", 94 | ":app:stripDebugDebugSymbols" : "NO_SOURCE", 95 | ":app:stripReleaseDebugSymbols" : "NO_SOURCE", 96 | ":app:validateSigningDebug" : "SUCCESS", 97 | ":app:writeDebugAppMetadata" : "SUCCESS", 98 | ":app:writeDebugSigningConfigVersions" : "SUCCESS", 99 | ":app:writeReleaseAppMetadata" : "SUCCESS", 100 | ":app:writeReleaseSigningConfigVersions" : "SUCCESS", 101 | ":library:assemble" : "SUCCESS", 102 | ":library:assembleDebug" : "SUCCESS", 103 | ":library:assembleRelease" : "SUCCESS", 104 | ":library:bundleDebugAar" : "SUCCESS", 105 | ":library:bundleLibCompileToJarDebug" : "SUCCESS", 106 | ":library:bundleLibCompileToJarRelease" : "SUCCESS", 107 | ":library:bundleLibRuntimeToDirDebug" : "SUCCESS", 108 | ":library:bundleLibRuntimeToDirRelease" : "SUCCESS", 109 | ":library:bundleLibRuntimeToJarDebug" : "SUCCESS", 110 | ":library:bundleLibRuntimeToJarRelease" : "SUCCESS", 111 | ":library:bundleReleaseAar" : "SUCCESS", 112 | ":library:compileDebugJavaWithJavac" : "FROM_CACHE", 113 | ":library:compileDebugKotlin" : "FROM_CACHE", 114 | ":library:compileDebugLibraryResources" : "FROM_CACHE", 115 | ":library:compileDebugShaders" : "NO_SOURCE", 116 | ":library:compileReleaseJavaWithJavac" : "FROM_CACHE", 117 | ":library:compileReleaseKotlin" : "FROM_CACHE", 118 | ":library:compileReleaseLibraryResources" : "FROM_CACHE", 119 | ":library:compileReleaseShaders" : "NO_SOURCE", 120 | ":library:copyDebugJniLibsProjectAndLocalJars" : "SUCCESS", 121 | ":library:copyDebugJniLibsProjectOnly" : "SUCCESS", 122 | ":library:copyReleaseJniLibsProjectAndLocalJars" : "SUCCESS", 123 | ":library:copyReleaseJniLibsProjectOnly" : "SUCCESS", 124 | ":library:createFullJarDebug" : "SUCCESS", 125 | ":library:createFullJarRelease" : "SUCCESS", 126 | ":library:dataBindingGenBaseClassesDebug" : "FROM_CACHE", 127 | ":library:dataBindingGenBaseClassesRelease" : "FROM_CACHE", 128 | ":library:dataBindingMergeDependencyArtifactsDebug" : "SUCCESS", 129 | ":library:dataBindingMergeDependencyArtifactsRelease": "SUCCESS", 130 | ":library:dataBindingTriggerDebug" : "SUCCESS", 131 | ":library:dataBindingTriggerRelease" : "SUCCESS", 132 | ":library:extractDebugAnnotations" : "FROM_CACHE", 133 | ":library:extractDeepLinksDebug" : "FROM_CACHE", 134 | ":library:extractDeepLinksForAarDebug" : "FROM_CACHE", 135 | ":library:extractDeepLinksForAarRelease" : "FROM_CACHE", 136 | ":library:extractDeepLinksRelease" : "FROM_CACHE", 137 | ":library:extractReleaseAnnotations" : "FROM_CACHE", 138 | ":library:generateDebugAssets" : "UP_TO_DATE", 139 | ":library:generateDebugResources" : "FROM_CACHE", 140 | ":library:generateDebugResValues" : "FROM_CACHE", 141 | ":library:generateDebugRFile" : "FROM_CACHE", 142 | ":library:generateReleaseAssets" : "UP_TO_DATE", 143 | ":library:generateReleaseResources" : "FROM_CACHE", 144 | ":library:generateReleaseResValues" : "FROM_CACHE", 145 | ":library:generateReleaseRFile" : "FROM_CACHE", 146 | ":library:javaPreCompileDebug" : "FROM_CACHE", 147 | ":library:javaPreCompileRelease" : "FROM_CACHE", 148 | ":library:kaptDebugKotlin" : "FROM_CACHE", 149 | ":library:kaptGenerateStubsDebugKotlin" : "FROM_CACHE", 150 | ":library:kaptGenerateStubsReleaseKotlin" : "FROM_CACHE", 151 | ":library:kaptReleaseKotlin" : "FROM_CACHE", 152 | ":library:mapReleaseSourceSetPaths" : "SUCCESS", 153 | ":library:mergeDebugConsumerProguardFiles" : "SUCCESS", 154 | ":library:mergeDebugGeneratedProguardFiles" : "SUCCESS", 155 | ":library:mergeDebugJavaResource" : "SUCCESS", 156 | ":library:mergeDebugJniLibFolders" : "SUCCESS", 157 | ":library:mergeDebugNativeLibs" : "NO_SOURCE", 158 | ":library:mergeDebugShaders" : "SUCCESS", 159 | ":library:mergeReleaseConsumerProguardFiles" : "SUCCESS", 160 | ":library:mergeReleaseGeneratedProguardFiles" : "SUCCESS", 161 | ":library:mergeReleaseJavaResource" : "SUCCESS", 162 | ":library:mergeReleaseJniLibFolders" : "SUCCESS", 163 | ":library:mergeReleaseNativeLibs" : "NO_SOURCE", 164 | ":library:mergeReleaseResources" : "FROM_CACHE", 165 | ":library:mergeReleaseShaders" : "SUCCESS", 166 | ":library:packageDebugAssets" : "SUCCESS", 167 | ":library:packageDebugResources" : "FROM_CACHE", 168 | ":library:packageReleaseAssets" : "SUCCESS", 169 | ":library:packageReleaseResources" : "FROM_CACHE", 170 | ":library:parseDebugLocalResources" : "FROM_CACHE", 171 | ":library:parseReleaseLocalResources" : "FROM_CACHE", 172 | ":library:preBuild" : "UP_TO_DATE", 173 | ":library:preDebugBuild" : "UP_TO_DATE", 174 | ":library:prepareDebugArtProfile" : "SUCCESS", 175 | ":library:prepareLintJarForPublish" : "SUCCESS", 176 | ":library:prepareReleaseArtProfile" : "SUCCESS", 177 | ":library:preReleaseBuild" : "UP_TO_DATE", 178 | ":library:processDebugJavaRes" : "SUCCESS", 179 | ":library:processDebugManifest" : "FROM_CACHE", 180 | ":library:processReleaseJavaRes" : "SUCCESS", 181 | ":library:processReleaseManifest" : "FROM_CACHE", 182 | ":library:stripDebugDebugSymbols" : "NO_SOURCE", 183 | ":library:stripReleaseDebugSymbols" : "NO_SOURCE", 184 | ":library:syncDebugLibJars" : "FROM_CACHE", 185 | ":library:syncReleaseLibJars" : "FROM_CACHE", 186 | ":library:verifyReleaseResources" : "FROM_CACHE", 187 | ":library:writeDebugAarMetadata" : "SUCCESS", 188 | ":library:writeReleaseAarMetadata" : "SUCCESS", 189 | ":app:checkKotlinGradlePluginConfigurationErrors" : "SKIPPED", 190 | ":library:checkKotlinGradlePluginConfigurationErrors": "SKIPPED" 191 | } 192 | -------------------------------------------------------------------------------- /src/test/resources/versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "testedVersions": { 3 | "8.12.0-alpha03": [ 4 | "8.14" 5 | ], 6 | "8.11.0-rc01": [ 7 | "8.13" 8 | ], 9 | "8.10.1": [ 10 | "8.12" 11 | ], 12 | "8.9.3": [ 13 | "8.12" 14 | ], 15 | "8.8.2": [ 16 | "8.12" 17 | ], 18 | "8.7.3": [ 19 | "8.12" 20 | ], 21 | "8.6.1": [ 22 | "8.12" 23 | ], 24 | "8.5.2": [ 25 | "8.12" 26 | ], 27 | "8.4.2": [ 28 | "8.12" 29 | ], 30 | "8.3.2": [ 31 | "8.12" 32 | ], 33 | "8.2.2": [ 34 | "8.12" 35 | ], 36 | "8.1.4": [ 37 | "8.12" 38 | ], 39 | "8.0.2": [ 40 | "8.0.2" 41 | ], 42 | "7.4.2": [ 43 | "7.6.2" 44 | ], 45 | "7.3.1": [ 46 | "7.4.2", 47 | "7.6.2" 48 | ], 49 | "7.2.2": [ 50 | "7.3.3", 51 | "7.6.2" 52 | ], 53 | "7.1.3": [ 54 | "7.2", 55 | "7.6.2" 56 | ], 57 | "7.0.4": [ 58 | "7.0.2", 59 | "7.6.2" 60 | ] 61 | } 62 | } 63 | --------------------------------------------------------------------------------