diff --git a/.github/workflows/dokka.yml b/.github/workflows/dokka.yml index 96d009ed4..df9d2d81e 100644 --- a/.github/workflows/dokka.yml +++ b/.github/workflows/dokka.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/setup-java@v3 with: distribution: 'adopt' - java-version: '11' + java-version: '17' cache: 'gradle' - shell: bash run: ./gradlew reference -S --no-daemon diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 1e108f431..2d58afe7a 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/setup-java@v3 with: distribution: 'adopt' - java-version: '11' + java-version: '17' cache: 'gradle' - shell: bash run: | @@ -24,8 +24,8 @@ jobs: echo $GPG_KEY_ARMOR | base64 --decode > $GITHUB_WORKSPACE/secring.gpg ./gradlew publishToSonatype closeAndReleaseStagingRepository -Pversion=${GITHUB_REF/refs\/tags\/v/} -POSSRH_USERNAME=${OSSRH_USERNAME} -POSSRH_PASSWORD=${OSSRH_PASSWORD} -POSSRH_STAGING_PROFILE_ID=${OSSRH_STAGING_PROFILE_ID} -Psigning.keyId=${GPG_KEY_ID} -Psigning.password=${GPG_PASSPHRASE} -Psigning.secretKeyRingFile=${GITHUB_WORKSPACE}/secring.gpg -S --no-daemon env: - JAVA_OPTS: -Xmx8g -XX:MaxPermSize=1g -XX:MetaspaceSize=1g -Dfile.encoding=UTF-8 - JVM_OPTS: -Xmx8g -XX:MaxPermSize=1g -XX:MetaspaceSize=1g -Dfile.encoding=UTF-8 + JAVA_OPTS: -Xmx8g -XX:MetaspaceSize=1g -Dfile.encoding=UTF-8 + JVM_OPTS: -Xmx8g -XX:MetaspaceSize=1g -Dfile.encoding=UTF-8 GPG_KEY_ARMOR: ${{ secrets.GPG_KEY_ARMOR }} GPG_KEY_ID: ${{ secrets.GPG_KEY_ID }} GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cdf96b391..7f16192a4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,7 +29,7 @@ jobs: - uses: actions/setup-java@v3 with: distribution: 'adopt' - java-version: '11' + java-version: '17' cache: 'gradle' - uses: actions/cache@v3 with: @@ -55,7 +55,7 @@ jobs: - uses: actions/setup-java@v3 with: distribution: 'adopt' - java-version: '11' + java-version: '17' cache: 'gradle' - uses: actions/cache@v3 with: @@ -73,8 +73,8 @@ jobs: name: unit-test-report path: '**/build/reports/tests/test' - integration-test-agp-v3_3: - name: AGP 3.3 Integration Test + integration-test-agp-v8_0: + name: AGP 8.0 Integration Test needs: build runs-on: ubuntu-latest steps: @@ -82,22 +82,22 @@ jobs: - uses: actions/setup-java@v3 with: distribution: 'adopt' - java-version: '11' + java-version: '17' cache: 'gradle' - uses: actions/cache@v3 with: path: ~/.m2 key: ${{ runner.os }}-m2-${{ github.run_number }} - shell: bash - run: ./gradlew booster-android-gradle-v3_3:integrationTest -S --no-daemon -Pversion=${{ github.run_number }} + run: ./gradlew booster-android-gradle-v8_0:integrationTest -S --no-daemon -Pversion=${{ github.run_number }} - uses: actions/upload-artifact@v3 if: failure() with: - name: booster-android-gradle-v3_3 - path: booster-android-gradle-v3_3/build/reports/tests/integrationTest + name: booster-android-gradle-v8_0 + path: booster-android-gradle-v8_0/build/reports/tests/integrationTest - integration-test-agp-v3_4: - name: AGP 3.4 Integration Test + integration-test-agp-v8_1: + name: AGP 8.1 Integration Test needs: build runs-on: ubuntu-latest steps: @@ -105,22 +105,22 @@ jobs: - uses: actions/setup-java@v3 with: distribution: 'adopt' - java-version: '11' + java-version: '17' cache: 'gradle' - uses: actions/cache@v3 with: path: ~/.m2 key: ${{ runner.os }}-m2-${{ github.run_number }} - shell: bash - run: ./gradlew booster-android-gradle-v3_4:integrationTest -S --no-daemon -Pversion=${{ github.run_number }} + run: ./gradlew booster-android-gradle-v8_1:integrationTest -S --no-daemon -Pversion=${{ github.run_number }} - uses: actions/upload-artifact@v3 if: failure() with: - name: booster-android-gradle-v3_4 - path: booster-android-gradle-v3_4/build/reports/tests/integrationTest + name: booster-android-gradle-v8_1 + path: booster-android-gradle-v8_1/build/reports/tests/integrationTest - integration-test-agp-v3_5: - name: AGP 3.5 Integration Test + integration-test-agp-v8_2: + name: AGP 8.2 Integration Test needs: build runs-on: ubuntu-latest steps: @@ -128,223 +128,16 @@ jobs: - uses: actions/setup-java@v3 with: distribution: 'adopt' - java-version: '11' + java-version: '17' cache: 'gradle' - uses: actions/cache@v3 with: path: ~/.m2 key: ${{ runner.os }}-m2-${{ github.run_number }} - shell: bash - run: ./gradlew booster-android-gradle-v3_5:integrationTest -S --no-daemon -Pversion=${{ github.run_number }} + run: ./gradlew booster-android-gradle-v8_2:integrationTest -S --no-daemon -Pversion=${{ github.run_number }} - uses: actions/upload-artifact@v3 if: failure() with: - name: booster-android-gradle-v3_5 - path: booster-android-gradle-v3_5/build/reports/tests/integrationTest - - integration-test-agp-v3_6: - name: AGP 3.6 Integration Test - needs: build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 - with: - distribution: 'adopt' - java-version: '11' - cache: 'gradle' - - uses: actions/cache@v3 - with: - path: ~/.m2 - key: ${{ runner.os }}-m2-${{ github.run_number }} - - shell: bash - run: ./gradlew booster-android-gradle-v3_6:integrationTest -S --no-daemon -Pversion=${{ github.run_number }} - - uses: actions/upload-artifact@v3 - if: failure() - with: - name: booster-android-gradle-v3_6 - path: booster-android-gradle-v3_6/build/reports/tests/integrationTest - - integration-test-agp-v4_0: - name: AGP 4.0 Integration Test - needs: build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 - with: - distribution: 'adopt' - java-version: '11' - cache: 'gradle' - - uses: actions/cache@v3 - with: - path: ~/.m2 - key: ${{ runner.os }}-m2-${{ github.run_number }} - - shell: bash - run: ./gradlew booster-android-gradle-v4_0:integrationTest -S --no-daemon -Pversion=${{ github.run_number }} - - uses: actions/upload-artifact@v3 - if: failure() - with: - name: booster-android-gradle-v4_0 - path: booster-android-gradle-v4_0/build/reports/tests/integrationTest - - integration-test-agp-v4_1: - name: AGP 4.1 Integration Test - needs: build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 - with: - distribution: 'adopt' - java-version: '11' - cache: 'gradle' - - uses: actions/cache@v3 - with: - path: ~/.m2 - key: ${{ runner.os }}-m2-${{ github.run_number }} - - shell: bash - run: ./gradlew booster-android-gradle-v4_1:integrationTest -S --no-daemon -Pversion=${{ github.run_number }} - - uses: actions/upload-artifact@v3 - if: failure() - with: - name: booster-android-gradle-v4_1 - path: booster-android-gradle-v4_1/build/reports/tests/integrationTest - - integration-test-agp-v4_2: - name: AGP 4.2 Integration Test - needs: build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 - with: - distribution: 'adopt' - java-version: '11' - cache: 'gradle' - - uses: actions/cache@v3 - with: - path: ~/.m2 - key: ${{ runner.os }}-m2-${{ github.run_number }} - - shell: bash - run: ./gradlew booster-android-gradle-v4_2:integrationTest -S --no-daemon -Pversion=${{ github.run_number }} - - uses: actions/upload-artifact@v3 - if: failure() - with: - name: booster-android-gradle-v4_2 - path: booster-android-gradle-v4_2/build/reports/tests/integrationTest - - integration-test-agp-v7_0: - name: AGP 7.0 Integration Test - needs: build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 - with: - distribution: 'adopt' - java-version: '11' - cache: 'gradle' - - uses: actions/cache@v3 - with: - path: ~/.m2 - key: ${{ runner.os }}-m2-${{ github.run_number }} - - shell: bash - run: ./gradlew booster-android-gradle-v7_0:integrationTest -S --no-daemon -Pversion=${{ github.run_number }} - - uses: actions/upload-artifact@v3 - if: failure() - with: - name: booster-android-gradle-v7_0 - path: booster-android-gradle-v7_0/build/reports/tests/integrationTest - - integration-test-agp-v7_1: - name: AGP 7.1 Integration Test - needs: build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 - with: - distribution: 'adopt' - java-version: '11' - cache: 'gradle' - - uses: actions/cache@v3 - with: - path: ~/.m2 - key: ${{ runner.os }}-m2-${{ github.run_number }} - - shell: bash - run: ./gradlew booster-android-gradle-v7_1:integrationTest -S --no-daemon -Pversion=${{ github.run_number }} - - uses: actions/upload-artifact@v3 - if: failure() - with: - name: booster-android-gradle-v7_1 - path: booster-android-gradle-v7_1/build/reports/tests/integrationTest - - integration-test-agp-v7_2: - name: AGP 7.2 Integration Test - needs: build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 - with: - distribution: 'adopt' - java-version: '11' - cache: 'gradle' - - uses: actions/cache@v3 - with: - path: ~/.m2 - key: ${{ runner.os }}-m2-${{ github.run_number }} - - shell: bash - run: ./gradlew booster-android-gradle-v7_2:integrationTest -S --no-daemon -Pversion=${{ github.run_number }} - - uses: actions/upload-artifact@v3 - if: failure() - with: - name: booster-android-gradle-v7_2 - path: booster-android-gradle-v7_2/build/reports/tests/integrationTest - - integration-test-agp-v7_3: - name: AGP 7.3 Integration Test - needs: build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 - with: - distribution: 'adopt' - java-version: '11' - cache: 'gradle' - - uses: actions/cache@v3 - with: - path: ~/.m2 - key: ${{ runner.os }}-m2-${{ github.run_number }} - - shell: bash - run: ./gradlew booster-android-gradle-v7_3:integrationTest -S --no-daemon -Pversion=${{ github.run_number }} - - uses: actions/upload-artifact@v3 - if: failure() - with: - name: booster-android-gradle-v7_3 - path: booster-android-gradle-v7_3/build/reports/tests/integrationTest - - integration-test-agp-v7_4: - name: AGP 7.4 Integration Test - needs: build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 - with: - distribution: 'adopt' - java-version: '11' - cache: 'gradle' - - uses: actions/cache@v3 - with: - path: ~/.m2 - key: ${{ runner.os }}-m2-${{ github.run_number }} - - shell: bash - run: ./gradlew booster-android-gradle-v7_4:integrationTest -S --no-daemon -Pversion=${{ github.run_number }} - - uses: actions/upload-artifact@v3 - if: failure() - with: - name: booster-android-gradle-v7_4 - path: booster-android-gradle-v7_4/build/reports/tests/integrationTest + name: booster-android-gradle-v8_2 + path: booster-android-gradle-v8_2/build/reports/tests/integrationTest \ No newline at end of file diff --git a/booster-aapt2/build.gradle b/booster-aapt2/build.gradle index 74077106e..88d5f8922 100644 --- a/booster-aapt2/build.gradle +++ b/booster-aapt2/build.gradle @@ -1,6 +1,6 @@ apply from: "$rootDir/gradle/booster.gradle" dependencies { - api 'com.google.protobuf:protobuf-java:3.10.0' - testImplementation 'com.android.tools.build:gradle:4.0.0' + api 'com.google.protobuf:protobuf-java:3.19.3' + testImplementation 'com.android.tools.build:gradle:8.0.0' } diff --git a/booster-android-api/src/main/java/android/os/Build.java b/booster-android-api/src/main/java/android/os/Build.java index 4a32e93f0..83302fde0 100644 --- a/booster-android-api/src/main/java/android/os/Build.java +++ b/booster-android-api/src/main/java/android/os/Build.java @@ -151,7 +151,6 @@ public static class VERSION { private static final String[] ALL_CODENAMES = getStringList("ro.build.version.all_codenames", ","); /** - * @hide */ public static final String[] ACTIVE_CODENAMES = "REL".equals(ALL_CODENAMES[0]) ? new String[0] : ALL_CODENAMES; @@ -161,7 +160,6 @@ public static class VERSION { * Use the current SDK version code. For every active development codename * we are operating under, we bump the assumed resource platform version by 1. * - * @hide */ public static final int RESOURCES_SDK_INT = SDK_INT + ACTIVE_CODENAMES.length; diff --git a/booster-android-api/src/main/java/android/util/Log.java b/booster-android-api/src/main/java/android/util/Log.java index 1ee313da7..d4a8b0c02 100644 --- a/booster-android-api/src/main/java/android/util/Log.java +++ b/booster-android-api/src/main/java/android/util/Log.java @@ -12,15 +12,14 @@ * into an application except during development. Debug logs are compiled * in but stripped at runtime. Error, warning and info logs are always kept. * - *

Tip: A good convention is to declare a TAG constant + * Tip: A good convention is to declare a TAG constant * in your class: * *

private static final String TAG = "MyActivity";
* * and use that in subsequent calls to the log methods. - *

* - *

Tip: Don't forget that when you make a call like + * Tip: Don't forget that when you make a call like *

Log.v(TAG, "index=" + i);
* that when you're building the string to pass into Log.d, the compiler uses a * StringBuilder and at least three allocations occur: the StringBuilder diff --git a/booster-android-api/src/main/java/android/view/ViewTreeObserver.java b/booster-android-api/src/main/java/android/view/ViewTreeObserver.java index c1b458330..2c8dc2fab 100644 --- a/booster-android-api/src/main/java/android/view/ViewTreeObserver.java +++ b/booster-android-api/src/main/java/android/view/ViewTreeObserver.java @@ -127,7 +127,6 @@ public interface OnScrollChangedListener { * This is only used for non-Activity windows. Activity windows can use * Activity.onEnterAnimationComplete() to get the same signal. * - * @hide */ public interface OnWindowShownListener { /** diff --git a/booster-android-gradle-api/build.gradle b/booster-android-gradle-api/build.gradle index 3258fbff7..334a8f42f 100644 --- a/booster-android-gradle-api/build.gradle +++ b/booster-android-gradle-api/build.gradle @@ -3,18 +3,9 @@ apply from: "$rootDir/gradle/booster.gradle" dependencies { api project(':booster-kotlinx') api project(':booster-android-gradle-compat') - implementation project(':booster-android-gradle-v3_3') - implementation project(':booster-android-gradle-v3_4') - implementation project(':booster-android-gradle-v3_5') - implementation project(':booster-android-gradle-v3_6') - implementation project(':booster-android-gradle-v4_0') - implementation project(':booster-android-gradle-v4_1') - implementation project(':booster-android-gradle-v4_2') - implementation project(':booster-android-gradle-v7_0') - implementation project(':booster-android-gradle-v7_1') - implementation project(':booster-android-gradle-v7_2') - implementation project(':booster-android-gradle-v7_3') - implementation project(':booster-android-gradle-v7_4') - compileOnly 'com.android.tools.build:gradle:3.0.0' - testCompileOnly 'com.android.tools.build:gradle:3.0.0' + implementation project(':booster-android-gradle-v8_0') + implementation project(':booster-android-gradle-v8_1') + implementation project(':booster-android-gradle-v8_2') + compileOnly 'com.android.tools.build:gradle:8.0.0' + testCompileOnly 'com.android.tools.build:gradle:8.0.0' } diff --git a/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/BaseVariant.kt b/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/BaseVariant.kt deleted file mode 100644 index 57472121f..000000000 --- a/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/BaseVariant.kt +++ /dev/null @@ -1,375 +0,0 @@ -package com.didiglobal.booster.gradle - -import com.android.build.gradle.BaseExtension -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.internal.publishing.AndroidArtifacts -import com.android.build.gradle.tasks.ProcessAndroidResources -import com.android.builder.model.ApiVersion -import com.android.sdklib.BuildToolInfo -import com.didiglobal.booster.kotlinx.file -import org.gradle.api.Incubating -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.UnknownTaskException -import org.gradle.api.artifacts.ArtifactCollection -import org.gradle.api.artifacts.result.ResolvedArtifactResult -import org.gradle.api.file.FileCollection -import org.gradle.api.provider.Provider -import org.gradle.api.tasks.TaskProvider -import java.io.File - -/** - * The project which this variant belongs - */ -@Suppress("DEPRECATION") -val BaseVariant.project: Project - get() = AGP.run { project } - - -fun BaseVariant.getReport(artifactName: String, fileName: String): File { - return project.buildDir.file("reports", artifactName, name, fileName) -} - - -/** - * The `android` extension associates with this variant - */ -val BaseVariant.extension: BaseExtension - get() = project.getAndroid() - -/** - * The location of `$ANDROID_HOME`/platforms/android-`${compileSdkVersion}` - */ -val BaseVariant.platform: File - get() = extension.run { - sdkDirectory.resolve("platforms").resolve(compileSdkVersion!!) - } - -/** - * The variant dependencies - */ -val BaseVariant.dependencies: Collection - get() = AGP.run { - getDependencies(true) - } - -val BaseVariant.javaCompilerTaskProvider: TaskProvider - get() = AGP.run { javaCompilerTaskProvider } - -val BaseVariant.preBuildTaskProvider: TaskProvider - get() = AGP.run { preBuildTaskProvider } - -val BaseVariant.assembleTaskProvider: TaskProvider - get() = AGP.run { assembleTaskProvider } - -val BaseVariant.mergeAssetsTaskProvider: TaskProvider - get() = AGP.run { mergeAssetsTaskProvider } - -val BaseVariant.mergeResourcesTaskProvider: TaskProvider - get() = AGP.run { mergeResourcesTaskProvider } - -val BaseVariant.mergeNativeLibsTaskProvider: TaskProvider - get() = AGP.run { mergeNativeLibsTaskProvider } - -val BaseVariant.processJavaResourcesTaskProvider: TaskProvider - get() = AGP.run { processJavaResourcesTaskProvider } - -val BaseVariant.processResTaskProvider: TaskProvider? - get() = try { - project.tasks.named(getTaskName("process", "Resources")) - } catch (_: UnknownTaskException) { - null - } - -val BaseVariant.bundleResourcesTaskProvider: TaskProvider? - get() = try { - project.tasks.named(getTaskName("bundle", "Resources")) - } catch (_: UnknownTaskException) { - null - } - -val BaseVariant.packageTaskProvider: TaskProvider? - get() = try { - project.tasks.named(getTaskName("package")) - } catch (_: UnknownTaskException) { - null - } - -val BaseVariant.packageBundleTaskProvider: TaskProvider? - get() = try { - project.tasks.named(getTaskName("package", "Bundle")) - } catch (_: UnknownTaskException) { - null - } - -val BaseVariant.mergeJavaResourceTaskProvider: TaskProvider? - get() = try { - project.tasks.named(getTaskName("merge", "JavaResource")) - } catch (_: UnknownTaskException) { - null - } - -val BaseVariant.createFullJarTaskProvider: TaskProvider? - get() = try { - project.tasks.named(getTaskName("createFullJar")) - } catch (_: UnknownTaskException) { - null - } - -val BaseVariant.bundleClassesTaskProvider: TaskProvider? - get() = try { - // for AGP < 7.2.0 - project.tasks.named(getTaskName("bundle", "Classes")) - } catch (_: UnknownTaskException) { - // for AGP >= 7.2.0+ - try { - project.tasks.named(getTaskName("bundle", "ClassesToRuntimeJar")) - } catch (_: UnknownTaskException) { - try { - project.tasks.named(getTaskName("bundle", "ClassesToCompileJar")) - } catch (_: UnknownTaskException) { - null - } - } - } - -fun BaseVariant.getTaskName(prefix: String): String = AGP.run { - getTaskName(prefix) -} - -fun BaseVariant.getTaskName(prefix: String, suffix: String): String = AGP.run { - getTaskName(prefix, suffix) -} - -val BaseVariant.minSdkVersion: ApiVersion - get() = AGP.run { - minSdkVersion - } - -val BaseVariant.isApplication: Boolean - get() = AGP.run { - isApplication - } - -val BaseVariant.isLibrary: Boolean - get() = AGP.run { - isLibrary - } - -val BaseVariant.isDynamicFeature: Boolean - get() = AGP.run { - isDynamicFeature - } - -val BaseVariant.originalApplicationId: String - get() = AGP.run { - originalApplicationId - } - -@Incubating -fun BaseVariant.getArtifactCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: AndroidArtifacts.ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType -): ArtifactCollection = AGP.run { - getArtifactCollection(configType, scope, artifactType) -} - -@Incubating -fun BaseVariant.getArtifactFileCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: AndroidArtifacts.ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType -): FileCollection = AGP.run { - getArtifactFileCollection(configType, scope, artifactType) -} - -val BaseVariant.aar: FileCollection - get() = AGP.run { - aar - } - -/** - * The output directory of APK files - */ -val BaseVariant.apk: FileCollection - get() = AGP.run { - apk - } - -/** - * The output directory of merged [AndroidManifest.xml](https://developer.android.com/guide/topics/manifest/manifest-intro) - */ -val BaseVariant.mergedManifests: FileCollection - get() = AGP.run { - mergedManifests - } - -/** - * The output directory of merged resources - */ -val BaseVariant.mergedRes: FileCollection - get() = AGP.run { - mergedRes - } - -/** - * The output directory of merged assets - */ -val BaseVariant.mergedAssets: FileCollection - get() = AGP.run { - mergedAssets - } - -/** - * The output directory of merged native libs - */ -val BaseVariant.mergedNativeLibs: FileCollection - get() = AGP.run { - mergedNativeLibs - } - -/** - * The output directory of processed resources: *resources-**variant**.ap\_* - */ -val BaseVariant.processedRes: FileCollection - get() = AGP.run { - processedRes - } - -/** - * All of classes - */ -val BaseVariant.allClasses: FileCollection - get() = AGP.run { - allClasses - } - -val BaseVariant.symbolList: FileCollection - get() = AGP.run { - symbolList - } - -val BaseVariant.symbolListWithPackageName: FileCollection - get() = AGP.run { - symbolListWithPackageName - } - -val BaseVariant.allArtifacts: Map - get() = AGP.run { - allArtifacts - } - -val BaseVariant.buildTools: BuildToolInfo - get() = AGP.run { - buildTools - } - -val BaseVariant.isPrecompileDependenciesResourcesEnabled: Boolean - get() = AGP.run { - isPrecompileDependenciesResourcesEnabled - } - -/** - * The `compileJava` task associates with this variant - */ -@Deprecated( - message = "Use javaCompilerTaskProvider instead", - replaceWith = ReplaceWith(expression = "javaCompilerTaskProvider"), - level = DeprecationLevel.WARNING -) -val BaseVariant.javaCompilerTask: Task - get() = AGP.run { javaCompilerTask } - -/** - * The `preBuild` task associates with this variant - */ -@Deprecated( - message = "Use preBuildTaskProvider instead", - replaceWith = ReplaceWith(expression = "preBuildTaskProvider"), - level = DeprecationLevel.WARNING -) -val BaseVariant.preBuildTask: Task - get() = AGP.run { preBuildTask } - -/** - * The `assemble` task associates with this variant - */ -@Deprecated( - message = "Use assembleTaskProvider instead", - replaceWith = ReplaceWith(expression = "assembleTaskProvider"), - level = DeprecationLevel.WARNING -) -val BaseVariant.assembleTask: Task - get() = AGP.run { assembleTask } - -/** - * The `mergeAssets` task associates with this variant - */ -@Deprecated( - message = "Use mergeAssetsTaskProvider instead", - replaceWith = ReplaceWith(expression = "mergeAssetsTaskProvider"), - level = DeprecationLevel.WARNING -) -val BaseVariant.mergeAssetsTask: Task - get() = AGP.run { mergeAssetsTask } - -/** - * The `mergeResources` task associates with this variant - */ -@Deprecated( - message = "Use mergeResourcesTaskProvider instead", - replaceWith = ReplaceWith(expression = "mergeResourcesTaskProvider"), - level = DeprecationLevel.WARNING -) -val BaseVariant.mergeResourcesTask: Task - get() = AGP.run { mergeResourcesTask } - -@Deprecated( - message = "Use processJavaResourcesTaskProvider instead", - replaceWith = ReplaceWith(expression = "processJavaResourcesTaskProvider"), - level = DeprecationLevel.WARNING -) -val BaseVariant.processJavaResourcesTask: Task - get() = AGP.run { processJavaResourcesTask } - -/** - * The `processRes` task associates with this variant - */ -@Deprecated( - message = "Use processResTaskProvider instead", - replaceWith = ReplaceWith(expression = "processResTaskProvider"), - level = DeprecationLevel.WARNING -) -val BaseVariant.processResTask: ProcessAndroidResources? - get() = project.tasks.findByName(getTaskName("process", "Resources")) as? ProcessAndroidResources - -/** - * The `bundleResources` tasks associates with this variant - */ -@Deprecated( - message = "Use bundleResourcesTaskProvider instead", - replaceWith = ReplaceWith(expression = "bundleResourcesTaskProvider"), - level = DeprecationLevel.WARNING -) -val BaseVariant.bundleResourcesTask: Task? - get() = project.tasks.findByName(getTaskName("bundle", "Resources")) - -/** - * The `packageBundle` tasks associates with this variant - */ -@Deprecated( - message = "Use packageBundleTaskProvider instead", - replaceWith = ReplaceWith(expression = "packageBundleTaskProvider"), - level = DeprecationLevel.WARNING -) -val BaseVariant.packageBundleTask: Task? - get() = project.tasks.findByName(getTaskName("package", "Bundle")) - -@Deprecated( - message = "Use mergeJavaResourceTaskProvider instead", - replaceWith = ReplaceWith(expression = "mergeJavaResourceTaskProvider"), - level = DeprecationLevel.WARNING -) -val BaseVariant.mergeJavaResourceTask: Task? - get() = project.tasks.findByName(getTaskName("merge", "JavaResource")) diff --git a/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/Context.kt b/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/Context.kt deleted file mode 100644 index aa6bdeb97..000000000 --- a/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/Context.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.didiglobal.booster.gradle - -import com.android.build.api.transform.Context -import com.android.build.gradle.internal.pipeline.TransformTask - -val Context.task: TransformTask - get() = AGP.run { task } \ No newline at end of file diff --git a/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/Project.kt b/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/Project.kt index 96abbb360..5e3060695 100644 --- a/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/Project.kt +++ b/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/Project.kt @@ -1,12 +1,10 @@ package com.didiglobal.booster.gradle -import com.android.build.gradle.AppExtension -import com.android.build.gradle.BaseExtension -import com.android.build.gradle.LibraryExtension -import com.android.build.gradle.api.BaseVariant +import com.android.build.api.variant.Variant +import com.android.build.gradle.internal.SdkComponentsBuildService +import com.android.build.gradle.internal.services.getBuildService import com.android.repository.Revision import org.gradle.api.Project -import org.gradle.api.Task import org.gradle.api.artifacts.component.ComponentArtifactIdentifier import org.gradle.api.artifacts.component.ComponentIdentifier import org.gradle.api.artifacts.component.ProjectComponentIdentifier @@ -16,10 +14,8 @@ import org.gradle.api.attributes.Attribute import org.gradle.api.attributes.AttributeContainer import org.gradle.api.capabilities.Capability import org.gradle.api.component.Artifact -import org.gradle.api.plugins.JavaPlugin import org.gradle.api.plugins.JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME import org.gradle.api.provider.Provider -import org.gradle.api.tasks.TaskProvider import org.gradle.maven.MavenPomArtifact import java.io.File import java.util.Optional @@ -31,17 +27,10 @@ import java.util.Stack val Project.gradleVersion: Revision get() = Revision.parseRevision(gradle.gradleVersion) -@Deprecated( - message = "Use isAapt2Enabled instead", - replaceWith = ReplaceWith( - expression = "isAapt2Enabled" - ) -) -val Project.aapt2Enabled: Boolean - get() = AGP.run { isAapt2Enabled } - -val Project.isAapt2Enabled: Boolean - get() = AGP.run { isAapt2Enabled } +val Project.androidSdkLocation: File + get() = getBuildService(gradle.sharedServices, SdkComponentsBuildService::class.java).flatMap { + it.sdkDirectoryProvider + }.get().asFile val Project.isAndroid: Boolean get() = plugins.hasPlugin("com.android.application") @@ -72,7 +61,7 @@ fun Project.getProperty(name: String, defaultValue: T): T { fun Project.getUpstreamProjects( transitive: Boolean = true, - variant: BaseVariant? = null + variant: Variant? = null ): Set = getResolvedArtifactResults(transitive, variant).mapNotNull { (it.id.componentIdentifier as? ProjectComponentIdentifier)?.projectPath?.let { projectPath -> rootProject.project(projectPath) @@ -81,12 +70,11 @@ fun Project.getUpstreamProjects( fun Project.getResolvedArtifactResults( transitive: Boolean = true, - variant: BaseVariant? = null + variant: Variant? = null ): Set = when { + variant == null -> emptySet() isAndroid -> getResolvedArtifactResultsRecursively(transitive) { - filterByVariant(variant).map { v -> - AGP.run { v.getDependencies(transitive) } - }.flatten() + AGP.run { variant.getDependencies(transitive) }.toList() } isJava -> getResolvedArtifactResultsRecursively(transitive) { configurations.getByName(RUNTIME_CLASSPATH_CONFIGURATION_NAME).resolvedConfiguration.resolvedArtifacts.map { @@ -123,43 +111,6 @@ private fun Project.getResolvedArtifactResultsRecursively(transitive: Boolean, r return results.values.toSet() } -/** - * Returns the jar files which could be the outputs of the jar task or createFullJar task - * - * @param variant The build variant - */ -fun Project.getJars(variant: BaseVariant? = null): Set = getJarTaskProviders(variant).map { - it.get().outputs.files -}.flatten().toSet() - -fun Project.getJarTaskProviders(variant: BaseVariant? = null): Collection> = when { - isAndroid -> when (getAndroidOrNull()) { - is LibraryExtension -> filterByVariant(variant).mapNotNull(BaseVariant::createFullJarTaskProvider) - is AppExtension -> filterByVariant(variant).mapNotNull(BaseVariant::bundleClassesTaskProvider) - else -> emptyList() - } - isJavaLibrary -> listOf(tasks.named(JavaPlugin.JAR_TASK_NAME)) - else -> emptyList() -} - -private fun Project.filterByVariant(variant: BaseVariant? = null): Collection { - val variants = when (val android = getAndroidOrNull()) { - is AppExtension -> android.applicationVariants - is LibraryExtension -> android.libraryVariants - else -> emptyList() - } - - if (null == variant) return variants - - return variants.filter { - it.name == variant.name - }.takeIf { - it.isNotEmpty() - } ?: variants.filter { - it.buildType.name == variant.buildType.name - } -} - private data class ResolvedArtifactResultImpl( private val artifactId: ComponentArtifactIdentifier, private val artifactFile: File diff --git a/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/ResolvedArtifactResults.kt b/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/ResolvedArtifactResults.kt index d06e43d55..45b93ccfb 100644 --- a/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/ResolvedArtifactResults.kt +++ b/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/ResolvedArtifactResults.kt @@ -1,11 +1,10 @@ package com.didiglobal.booster.gradle -import com.android.build.gradle.api.BaseVariant +import com.android.build.api.variant.Variant import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactScope.ALL import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactType.AAR import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactType.JAR import com.android.build.gradle.internal.publishing.AndroidArtifacts.ConsumedConfigType.RUNTIME_CLASSPATH -import com.android.builder.model.AndroidProject import com.didiglobal.booster.kotlinx.file import com.didiglobal.booster.kotlinx.separatorsToSystem import com.didiglobal.booster.kotlinx.touch @@ -21,10 +20,10 @@ import java.io.PrintWriter @Suppress("UnstableApiUsage") @Deprecated( message = "Use AGPInterface instead", - replaceWith = ReplaceWith("BaseVariant.getDependencies(Boolean, (ComponentIdentifier) -> Boolean)"), + replaceWith = ReplaceWith("Variant.getDependencies(Boolean, (ComponentIdentifier) -> Boolean)"), level = DeprecationLevel.WARNING ) -class ResolvedArtifactResults(private val variant: BaseVariant) : Collection { +class ResolvedArtifactResults(private val variant: Variant) : Collection { private val results = listOf(AAR, JAR) .asSequence() @@ -80,9 +79,9 @@ class ResolvedArtifactResults(private val variant: BaseVariant) : Collection - get() = AGP.run { bootClasspath } - -/** - * Returns the compile classpath of this transform invocation - * - * @author johnsonlee - */ -val TransformInvocation.compileClasspath: Collection - get() = listOf(inputs, referencedInputs).flatten().map { - it.jarInputs + it.directoryInputs - }.flatten().map { - it.file - } - -/** - * Returns the runtime classpath of this transform invocation - * - * @author johnsonlee - */ -val TransformInvocation.runtimeClasspath: Collection - get() = compileClasspath + bootClasspath - -/** - * Returns the application id - */ -val TransformInvocation.applicationId: String - get() = variant.applicationId - -/** - * Returns the original application ID before any overrides from flavors - */ -val TransformInvocation.originalApplicationId: String - get() = variant.originalApplicationId - -val TransformInvocation.isDataBindingEnabled: Boolean - get() = AGP.run { isDataBindingEnabled } diff --git a/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/TransformManager.kt b/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/TransformManager.kt deleted file mode 100644 index 0df666e70..000000000 --- a/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/TransformManager.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.didiglobal.booster.gradle - -import com.android.build.api.transform.QualifiedContent -import com.android.build.gradle.internal.pipeline.TransformManager - -val SCOPE_PROJECT: MutableSet = TransformManager.PROJECT_ONLY - -val SCOPE_FULL_PROJECT: MutableSet = TransformManager.SCOPE_FULL_PROJECT - -val SCOPE_FULL_WITH_FEATURES: MutableSet = AGP.run { - scopeFullWithFeatures -} - -val SCOPE_FULL_LIBRARY_WITH_FEATURES: MutableSet = AGP.run { - scopeFullLibraryWithFeatures -} diff --git a/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/Variant.kt b/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/Variant.kt new file mode 100644 index 000000000..5a4af51da --- /dev/null +++ b/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/Variant.kt @@ -0,0 +1,262 @@ +package com.didiglobal.booster.gradle + +import com.android.build.api.artifact.Artifact +import com.android.build.api.variant.AndroidVersion +import com.android.build.api.variant.Variant +import com.android.build.gradle.internal.SdkComponentsBuildService +import com.android.build.gradle.internal.publishing.AndroidArtifacts +import com.android.build.gradle.internal.services.getBuildService +import com.android.sdklib.BuildToolInfo +import org.apache.groovy.lang.annotation.Incubating +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.UnknownTaskException +import org.gradle.api.artifacts.ArtifactCollection +import org.gradle.api.artifacts.result.ResolvedArtifactResult +import org.gradle.api.file.FileCollection +import org.gradle.api.file.FileSystemLocation +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.TaskProvider +import java.io.File + +/** + * The project which this variant belongs + */ +val Variant.project: Project + get() = AGP.run { project } + +/** + * The location of `$ANDROID_HOME`/platforms/android-`${compileSdkVersion}` + */ +val Variant.platform: File + get() = getBuildService(project.gradle.sharedServices, SdkComponentsBuildService::class.java).flatMap { + it.sdkDirectoryProvider + }.get().asFile.resolve("platform").resolve("android-${targetVersion.apiLevel}") + +/** + * The variant dependencies + */ +val Variant.dependencies: Collection + get() = AGP.run { + getDependencies(true) + } + +val Variant.targetVersion: AndroidVersion + get() = AGP.run { targetVersion } + +val Variant.javaCompilerTaskProvider: TaskProvider + get() = AGP.run { javaCompilerTaskProvider } + +val Variant.preBuildTaskProvider: TaskProvider + get() = AGP.run { preBuildTaskProvider } + +val Variant.assembleTaskProvider: TaskProvider + get() = AGP.run { assembleTaskProvider } + +val Variant.mergeAssetsTaskProvider: TaskProvider + get() = AGP.run { mergeAssetsTaskProvider } + +val Variant.mergeResourcesTaskProvider: TaskProvider + get() = AGP.run { mergeResourcesTaskProvider } + +val Variant.mergeNativeLibsTaskProvider: TaskProvider + get() = AGP.run { mergeNativeLibsTaskProvider } + +val Variant.processJavaResourcesTaskProvider: TaskProvider + get() = AGP.run { processJavaResourcesTaskProvider } + +val Variant.processResTaskProvider: TaskProvider? + get() = try { + project.tasks.named(getTaskName("process", "Resources")) + } catch (_: UnknownTaskException) { + null + } + +val Variant.bundleResourcesTaskProvider: TaskProvider? + get() = try { + project.tasks.named(getTaskName("bundle", "Resources")) + } catch (_: UnknownTaskException) { + null + } + +val Variant.packageTaskProvider: TaskProvider? + get() = try { + project.tasks.named(getTaskName("package")) + } catch (_: UnknownTaskException) { + null + } + +val Variant.packageBundleTaskProvider: TaskProvider? + get() = try { + project.tasks.named(getTaskName("package", "Bundle")) + } catch (_: UnknownTaskException) { + null + } + +val Variant.mergeJavaResourceTaskProvider: TaskProvider? + get() = try { + project.tasks.named(getTaskName("merge", "JavaResource")) + } catch (_: UnknownTaskException) { + null + } + +val Variant.createFullJarTaskProvider: TaskProvider? + get() = try { + project.tasks.named(getTaskName("createFullJar")) + } catch (_: UnknownTaskException) { + null + } + +val Variant.bundleClassesTaskProvider: TaskProvider? + get() = try { + project.tasks.named(getTaskName("bundle", "ClassesToRuntimeJar")) + } catch (_: UnknownTaskException) { + try { + project.tasks.named(getTaskName("bundle", "ClassesToCompileJar")) + } catch (_: UnknownTaskException) { + null + } + } + +fun Variant.getTaskName(prefix: String): String = AGP.run { + getTaskName(prefix) +} + +fun Variant.getTaskName(prefix: String, suffix: String): String = AGP.run { + getTaskName(prefix, suffix) +} + +val Variant.isApplication: Boolean + get() = AGP.run { + isApplication + } + +val Variant.isLibrary: Boolean + get() = AGP.run { + isLibrary + } + +val Variant.isDynamicFeature: Boolean + get() = AGP.run { + isDynamicFeature + } + +val Variant.originalApplicationId: String + get() = AGP.run { + originalApplicationId + } + +fun Variant.getSingleArtifact( + type: Artifact.Single +): Provider = AGP.run { + getSingleArtifact(type) +} + +@Incubating +fun Variant.getArtifactCollection( + configType: AndroidArtifacts.ConsumedConfigType, + scope: AndroidArtifacts.ArtifactScope, + artifactType: AndroidArtifacts.ArtifactType +): ArtifactCollection = AGP.run { + getArtifactCollection(configType, scope, artifactType) +} + +@Incubating +fun Variant.getArtifactFileCollection( + configType: AndroidArtifacts.ConsumedConfigType, + scope: AndroidArtifacts.ArtifactScope, + artifactType: AndroidArtifacts.ArtifactType +): FileCollection = AGP.run { + getArtifactFileCollection(configType, scope, artifactType) +} + +val Variant.aar: FileCollection + get() = AGP.run { + aar + } + +val Variant.resourceSetMap: FileCollection + get() = AGP.run { + sourceSetMap + } + +/** + * The output directory of APK files + */ +val Variant.apk: FileCollection + get() = AGP.run { + apk + } + +/** + * The output directory of merged [AndroidManifest.xml](https://developer.android.com/guide/topics/manifest/manifest-intro) + */ +val Variant.mergedManifests: FileCollection + get() = AGP.run { + mergedManifests + } + +/** + * The output directory of merged resources + */ +val Variant.mergedRes: FileCollection + get() = AGP.run { + mergedRes + } + +/** + * The output directory of merged assets + */ +val Variant.mergedAssets: FileCollection + get() = AGP.run { + mergedAssets + } + +/** + * The output directory of merged native libs + */ +val Variant.mergedNativeLibs: FileCollection + get() = AGP.run { + mergedNativeLibs + } + +/** + * The output directory of processed resources: *resources-**variant**.ap\_* + */ +val Variant.processedRes: FileCollection + get() = AGP.run { + processedRes + } + +/** + * All of classes + */ +val Variant.allClasses: FileCollection + get() = AGP.run { + allClasses + } + +val Variant.symbolList: FileCollection + get() = AGP.run { + symbolList + } + +val Variant.symbolListWithPackageName: FileCollection + get() = AGP.run { + symbolListWithPackageName + } + +val Variant.allArtifacts: Map + get() = AGP.run { + allArtifacts + } + +val Variant.buildTools: BuildToolInfo + get() = AGP.run { + buildTools + } + +val Variant.isPrecompileDependenciesResourcesEnabled: Boolean + get() = AGP.run { + isPrecompileDependenciesResourcesEnabled + } diff --git a/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/Version.kt b/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/Version.kt index 6e87bc531..48b5dba45 100644 --- a/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/Version.kt +++ b/booster-android-gradle-api/src/main/kotlin/com/didiglobal/booster/gradle/Version.kt @@ -1,19 +1,7 @@ package com.didiglobal.booster.gradle -val GTE_V3_X: Boolean by lazy { AGP.revision.major >= 3 } -val GTE_V3_6: Boolean by lazy { AGP.revision.major > 3 || (AGP.revision.major == 3 && AGP.revision.minor >= 6) } -val GTE_V3_5: Boolean by lazy { AGP.revision.major > 3 || (AGP.revision.major == 3 && AGP.revision.minor >= 5) } -val GTE_V3_4: Boolean by lazy { AGP.revision.major > 3 || (AGP.revision.major == 3 && AGP.revision.minor >= 4) } -val GTE_V3_3: Boolean by lazy { AGP.revision.major > 3 || (AGP.revision.major == 3 && AGP.revision.minor >= 3) } -val GTE_V3_2: Boolean by lazy { AGP.revision.major > 3 || (AGP.revision.major == 3 && AGP.revision.minor >= 2) } -val GTE_V3_1: Boolean by lazy { AGP.revision.major > 3 || (AGP.revision.major == 3 && AGP.revision.minor >= 1) } +val GTE_V8_X: Boolean by lazy { AGP.revision.major >= 8 } -val GTE_V4_X: Boolean by lazy { AGP.revision.major >= 4 } -val GTE_V4_2: Boolean by lazy { AGP.revision.major > 4 || (AGP.revision.major == 4 && AGP.revision.minor >= 2) } -val GTE_V4_1: Boolean by lazy { AGP.revision.major > 4 || (AGP.revision.major == 4 && AGP.revision.minor >= 1) } +val GTE_V8_1: Boolean by lazy { AGP.revision.major > 8 || (AGP.revision.major == 8 && AGP.revision.minor >= 1) } -val GTE_V7_X: Boolean by lazy { AGP.revision.major >= 7 } -val GTE_V7_4: Boolean by lazy { AGP.revision.major > 7 || (AGP.revision.major == 7 && AGP.revision.minor >= 4) } -val GTE_V7_3: Boolean by lazy { AGP.revision.major > 7 || (AGP.revision.major == 7 && AGP.revision.minor >= 3) } -val GTE_V7_2: Boolean by lazy { AGP.revision.major > 7 || (AGP.revision.major == 7 && AGP.revision.minor >= 2) } -val GTE_V7_1: Boolean by lazy { AGP.revision.major > 7 || (AGP.revision.major == 7 && AGP.revision.minor >= 1) } +val GTE_V8_2: Boolean by lazy { AGP.revision.major > 8 || (AGP.revision.major == 8 && AGP.revision.minor >= 2) } diff --git a/booster-android-gradle-compat/build.gradle b/booster-android-gradle-compat/build.gradle index 49cacd5c7..899e1b1e8 100644 --- a/booster-android-gradle-compat/build.gradle +++ b/booster-android-gradle-compat/build.gradle @@ -4,8 +4,8 @@ dependencies { api gradleApi() api 'com.android.tools:repository:26.0.0' api 'com.android.tools:sdklib:26.0.0' - compileOnly 'com.android.tools.build:gradle:3.0.0' - testCompileOnly 'com.android.tools.build:gradle:3.0.0' + compileOnly 'com.android.tools.build:gradle:8.0.0' + testCompileOnly 'com.android.tools.build:gradle:8.0.0' testApi project(':booster-build') testApi gradleTestKit() testApi 'org.spockframework:spock-core:1.3-groovy-2.5' diff --git a/booster-android-gradle-compat/src/main/kotlin/com/didiglobal/booster/gradle/AGPInterface.kt b/booster-android-gradle-compat/src/main/kotlin/com/didiglobal/booster/gradle/AGPInterface.kt index a417adea5..673a9fa6b 100644 --- a/booster-android-gradle-compat/src/main/kotlin/com/didiglobal/booster/gradle/AGPInterface.kt +++ b/booster-android-gradle-compat/src/main/kotlin/com/didiglobal/booster/gradle/AGPInterface.kt @@ -1,18 +1,12 @@ package com.didiglobal.booster.gradle -import com.android.build.api.transform.Context -import com.android.build.api.transform.QualifiedContent -import com.android.build.api.transform.TransformInvocation -import com.android.build.gradle.AppExtension +import com.android.build.api.artifact.Artifact +import com.android.build.api.variant.AndroidComponentsExtension +import com.android.build.api.variant.AndroidVersion +import com.android.build.api.variant.Variant import com.android.build.gradle.BaseExtension -import com.android.build.gradle.LibraryExtension -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.internal.pipeline.TransformManager -import com.android.build.gradle.internal.pipeline.TransformTask import com.android.build.gradle.internal.publishing.AndroidArtifacts -import com.android.build.gradle.internal.scope.VariantScope import com.android.build.gradle.internal.variant.BaseVariantData -import com.android.builder.model.ApiVersion import com.android.builder.model.Version import com.android.repository.Revision import com.android.sdklib.BuildToolInfo @@ -23,8 +17,9 @@ import org.gradle.api.artifacts.ArtifactCollection import org.gradle.api.artifacts.component.ComponentIdentifier import org.gradle.api.artifacts.result.ResolvedArtifactResult import org.gradle.api.file.FileCollection +import org.gradle.api.file.FileSystemLocation +import org.gradle.api.provider.Provider import org.gradle.api.tasks.TaskProvider -import java.io.File import java.util.ServiceLoader interface AGPInterface { @@ -32,20 +27,14 @@ interface AGPInterface { val revision: Revision get() = REVISION - val scopeFullWithFeatures: MutableSet - get() = TransformManager.SCOPE_FULL_PROJECT - - val scopeFullLibraryWithFeatures: MutableSet - get() = TransformManager.PROJECT_ONLY - - val BaseVariant.project: Project + val Variant.project: Project @Deprecated( message = "Use javaCompilerTaskProvider instead", replaceWith = ReplaceWith(expression = "javaCompilerTaskProvider"), level = DeprecationLevel.WARNING ) - val BaseVariant.javaCompilerTask: Task + val Variant.javaCompilerTask: Task get() = javaCompilerTaskProvider.get() @Deprecated( @@ -53,7 +42,7 @@ interface AGPInterface { replaceWith = ReplaceWith(expression = "preBuildTaskProvider"), level = DeprecationLevel.WARNING ) - val BaseVariant.preBuildTask: Task + val Variant.preBuildTask: Task get() = preBuildTaskProvider.get() @Deprecated( @@ -61,7 +50,7 @@ interface AGPInterface { replaceWith = ReplaceWith(expression = "preBuildTaskProvider"), level = DeprecationLevel.WARNING ) - val BaseVariant.assembleTask: Task + val Variant.assembleTask: Task get() = assembleTaskProvider.get() @Deprecated( @@ -69,7 +58,7 @@ interface AGPInterface { replaceWith = ReplaceWith(expression = "mergeAssetsTaskProvider"), level = DeprecationLevel.WARNING ) - val BaseVariant.mergeAssetsTask: Task + val Variant.mergeAssetsTask: Task get() = mergeAssetsTaskProvider.get() @Deprecated( @@ -77,7 +66,7 @@ interface AGPInterface { replaceWith = ReplaceWith(expression = "mergeResourcesTaskProvider"), level = DeprecationLevel.WARNING ) - val BaseVariant.mergeResourcesTask: Task + val Variant.mergeResourcesTask: Task get() = mergeResourcesTaskProvider.get() @@ -86,145 +75,121 @@ interface AGPInterface { replaceWith = ReplaceWith(expression = "processJavaResourcesTaskProvider"), level = DeprecationLevel.WARNING ) - val BaseVariant.processJavaResourcesTask: Task + val Variant.processJavaResourcesTask: Task get() = processJavaResourcesTaskProvider.get() - fun BaseVariant.getTaskName(prefix: String): String + fun Variant.getTaskName(prefix: String): String - fun BaseVariant.getTaskName(prefix: String, suffix: String): String + fun Variant.getTaskName(prefix: String, suffix: String): String - val BaseVariant.variantData: BaseVariantData + val Variant.variantData: BaseVariantData @Deprecated( - message = "Use BaseVariant.namespace instead", + message = "Use Variant.namespace instead", replaceWith = ReplaceWith(expression = "variant.namespace"), ) - val BaseVariant.originalApplicationId: String + val Variant.originalApplicationId: String - val BaseVariant.hasDynamicFeature: Boolean + val Variant.hasDynamicFeature: Boolean @Deprecated(message = "Deprecated, don't use it") - val BaseVariant.rawAndroidResources: FileCollection + val Variant.rawAndroidResources: FileCollection + + val Variant.sourceSetMap: FileCollection + + val Variant.localAndroidResources: FileCollection - val BaseVariant.localAndroidResources: FileCollection + val Variant.javaCompilerTaskProvider: TaskProvider - val BaseVariant.javaCompilerTaskProvider: TaskProvider + val Variant.preBuildTaskProvider: TaskProvider - val BaseVariant.preBuildTaskProvider: TaskProvider + val Variant.assembleTaskProvider: TaskProvider - val BaseVariant.assembleTaskProvider: TaskProvider + val Variant.mergeAssetsTaskProvider: TaskProvider - val BaseVariant.mergeAssetsTaskProvider: TaskProvider + val Variant.mergeResourcesTaskProvider: TaskProvider - val BaseVariant.mergeResourcesTaskProvider: TaskProvider + val Variant.mergeNativeLibsTaskProvider: TaskProvider - val BaseVariant.mergeNativeLibsTaskProvider: TaskProvider + val Variant.processJavaResourcesTaskProvider: TaskProvider - val BaseVariant.processJavaResourcesTaskProvider: TaskProvider + fun Variant.getSingleArtifact( + type: Artifact.Single + ): Provider - fun BaseVariant.getArtifactCollection( + fun Variant.getArtifactCollection( configType: AndroidArtifacts.ConsumedConfigType, scope: AndroidArtifacts.ArtifactScope, artifactType: AndroidArtifacts.ArtifactType ): ArtifactCollection - fun BaseVariant.getArtifactFileCollection( + fun Variant.getArtifactFileCollection( configType: AndroidArtifacts.ConsumedConfigType, scope: AndroidArtifacts.ArtifactScope, artifactType: AndroidArtifacts.ArtifactType ): FileCollection - val BaseVariant.allArtifacts: Map + val Variant.allArtifacts: Map - val BaseVariant.minSdkVersion: ApiVersion + val Variant.targetVersion: AndroidVersion - val BaseVariant.targetSdkVersion: ApiVersion + val Variant.isApplication: Boolean - val BaseVariant.isApplication: Boolean + val Variant.isLibrary: Boolean - val BaseVariant.isLibrary: Boolean + val Variant.isDynamicFeature: Boolean - val BaseVariant.isDynamicFeature: Boolean + val Variant.aar: FileCollection - val BaseVariant.aar: FileCollection + val Variant.apk: FileCollection - val BaseVariant.apk: FileCollection + val Variant.mergedManifests: FileCollection - val BaseVariant.mergedManifests: FileCollection + val Variant.mergedRes: FileCollection - val BaseVariant.mergedRes: FileCollection + val Variant.mergedAssets: FileCollection - val BaseVariant.mergedAssets: FileCollection + val Variant.mergedNativeLibs: FileCollection - val BaseVariant.mergedNativeLibs: FileCollection + val Variant.processedRes: FileCollection - val BaseVariant.processedRes: FileCollection + val Variant.symbolList: FileCollection - val BaseVariant.symbolList: FileCollection + val Variant.symbolListWithPackageName: FileCollection - val BaseVariant.symbolListWithPackageName: FileCollection + val Variant.dataBindingDependencyArtifacts: FileCollection - val BaseVariant.dataBindingDependencyArtifacts: FileCollection + val Variant.allClasses: FileCollection - val BaseVariant.allClasses: FileCollection + val Variant.buildTools: BuildToolInfo - val BaseVariant.buildTools: BuildToolInfo + val Variant.isPrecompileDependenciesResourcesEnabled: Boolean - val BaseVariant.isPrecompileDependenciesResourcesEnabled: Boolean - - fun BaseVariant.getDependencies( + fun Variant.getDependencies( transitive: Boolean = true, filter: (ComponentIdentifier) -> Boolean = { true } ): Collection - val Context.task: TransformTask - - @Deprecated( - message = "Use isAapt2Enabled instead", - replaceWith = ReplaceWith( - expression = "isAapt2Enabled" - ) - ) - val Project.aapt2Enabled: Boolean - - @Suppress("DEPRECATION") - val Project.isAapt2Enabled: Boolean - get() = aapt2Enabled - - val TransformInvocation.variant: BaseVariant - get() = project.getAndroid().let { android -> - this.context.variantName.let { variant -> - when (android) { - is AppExtension -> when { - variant.endsWith("AndroidTest") -> android.testVariants.single { it.name == variant } - variant.endsWith("UnitTest") -> android.unitTestVariants.single { it.name == variant } - else -> android.applicationVariants.single { it.name == variant } - } - is LibraryExtension -> android.libraryVariants.single { it.name == variant } - else -> TODO("variant not found") - } - } - } - - val TransformInvocation.project: Project - get() = context.task.project - - val TransformInvocation.bootClasspath: Collection - get() = project.getAndroid().bootClasspath - - val TransformInvocation.isDataBindingEnabled: Boolean - get() = project.getAndroid().dataBinding.isEnabled - } +@Deprecated("Deprecated", ReplaceWith("getAndroidComponent")) inline fun Project.getAndroid(): T = extensions.getByName("android") as T +@Deprecated("Deprecated", ReplaceWith("getAndroidComponent")) inline fun Project.getAndroidOrNull(): T? = try { extensions.getByName("android") as? T } catch (e: UnknownDomainObjectException) { null } +inline fun > Project.getAndroidComponents() = extensions.getByType(AndroidComponentsExtension::class.java) as T + +inline fun > Project.getAndroidComponentsOrNull() = try { + getAndroidComponents() +} catch (e: UnknownDomainObjectException) { + null +} + private val REVISION: Revision by lazy { Revision.parseRevision(Version.ANDROID_GRADLE_PLUGIN_VERSION) } diff --git a/booster-android-gradle-v3_3/README.md b/booster-android-gradle-v3_3/README.md deleted file mode 100644 index 715630dc5..000000000 --- a/booster-android-gradle-v3_3/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# booster-android-gradle-v3_3 - -This module is an implementation of [booster-android-gradle-api](../booster-android-gradle-api) for Android gradle plugin 3.3 and above. - -本模块是 [booster-android-gradle-api](../booster-android-gradle-api) 针对 Android gradle plugin 3.3 以上版本的实现。 - diff --git a/booster-android-gradle-v3_3/build.gradle b/booster-android-gradle-v3_3/build.gradle deleted file mode 100644 index 7fc6eb17b..000000000 --- a/booster-android-gradle-v3_3/build.gradle +++ /dev/null @@ -1,19 +0,0 @@ -apply plugin: 'java-gradle-plugin' - -apply from: "$rootDir/gradle/booster.gradle" -apply from: "$rootDir/gradle/integration-test.gradle" -apply from: "$rootDir/gradle/functional-test.gradle" - -dependencies { - kapt 'com.google.auto.service:auto-service:1.0' - api 'com.google.auto.service:auto-service:1.0' - api project(':booster-android-gradle-compat') - compileOnly 'com.android.tools.build:gradle:3.3.0' - testImplementation 'com.android.tools.build:gradle:3.3.0' - testImplementation 'io.bootstage.testkit:testkit-gradle-plugin:1.4.0' - testImplementation project(':booster-build') -} - -gradlePlugin { - testSourceSets sourceSets.functionalTest, sourceSets.integrationTest -} \ No newline at end of file diff --git a/booster-android-gradle-v3_3/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v3_3/V33IntegrationTest.kt b/booster-android-gradle-v3_3/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v3_3/V33IntegrationTest.kt deleted file mode 100644 index 84595ce26..000000000 --- a/booster-android-gradle-v3_3/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v3_3/V33IntegrationTest.kt +++ /dev/null @@ -1,475 +0,0 @@ -@file:Suppress("DEPRECATION") - -package com.didiglobal.booster.android.gradle.v3_3 - -import com.android.build.gradle.AppExtension -import com.android.build.gradle.BaseExtension -import com.android.build.gradle.LibraryExtension -import com.android.build.gradle.api.BaseVariant -import com.android.sdklib.BuildToolInfo -import com.didiglobal.booster.gradle.AGP -import com.didiglobal.booster.gradle.getAndroid -import com.didiglobal.booster.kotlinx.search -import io.bootstage.testkit.gradle.Case -import io.bootstage.testkit.gradle.TestCase -import io.bootstage.testkit.gradle.VariantTestCase -import io.bootstage.testkit.gradle.rules.GradleExecutor -import io.bootstage.testkit.gradle.rules.LocalProperties -import io.bootstage.testkit.gradle.rules.copyFromResource -import io.bootstage.testkit.gradle.rules.rule -import org.gradle.api.Project -import org.junit.Before -import org.junit.Rule -import org.junit.rules.TemporaryFolder -import org.junit.rules.TestRule -import java.io.File -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertNotNull -import kotlin.test.assertTrue -import kotlin.test.fail - -private val MIN_SDK_VERSION = System.getProperty("android.minsdk.version").toInt() - -private const val TARGET_SDK_VERSION = 26 - -private val ARGS = System.getProperty("gradle.args").split("\\s+".toRegex()) + listOf( - "-Pbooster_version=${Build.VERSION}", - "-Pandroid_gradle_version=3.3.0", - "-Pcompile_sdk_version=28", - "-Pbuild_tools_version=26.0.3", - "-Pmin_sdk_version=${MIN_SDK_VERSION}", - "-Ptarget_sdk_version=${TARGET_SDK_VERSION}" -) - -@Suppress("RemoveCurlyBracesFromTemplate", "FunctionName") -abstract class V33IntegrationTest(private val isLib: Boolean) { - - private val projectDir = TemporaryFolder() - - @get:Rule - val ruleChain: TestRule = rule(projectDir) { - rule(LocalProperties(projectDir::getRoot)) { - GradleExecutor(projectDir::getRoot, "4.10.1", *ARGS.toTypedArray()) - } - } - - @Before - fun setup() { - projectDir.copyFromResource("${if (isLib) "lib" else "app"}.gradle", "build.gradle") - projectDir.copyFromResource("buildSrc") - projectDir.copyFromResource("src") - projectDir.newFile("gradle.properties").writeText("org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=2g") - assertEquals(3, AGP.revision.major) - assertEquals(3, AGP.revision.minor) - } - - @Test - @Case(ScopeFullWithFeaturesTest::class) - fun `test AGPInterface#scopeFullWithFeatures`() = Unit - - @Test - @Case(ScopeFullLibraryWithFeaturesTest::class) - fun `test AGPInterface#scopeFullLibraryWithFeatures`() = Unit - - @Test - @Case(ProjectTest::class) - fun `test AGPInterface#project`() = Unit - - @Test - @Case(JavaCompilerTaskTestUnit::class) - fun `test AGPInterface#javaCompilerTask`() = Unit - - @Test - @Case(PreBuildTaskTestUnit::class) - fun `test AGPInterface#preBuildTask`() = Unit - - @Test - @Case(AssembleTaskTestUnit::class) - fun `test AGPInterface#assembleTask`() = Unit - - @Test - @Case(MergeAssetsTaskTestUnit::class) - fun `test AGPInterface#mergeAssetsTask`() = Unit - - @Test - @Case(MergeResourcesTaskTestUnit::class) - fun `test AGPInterface#mergeResources`() = Unit - - @Test - @Case(GetTaskNameTestUnit::class) - fun `test AGPInterface#getTaskName(String)`() = Unit - - @Test - @Case(GetTaskName2TestUnit::class) - fun `test AGPInterface#getTaskName(String, String)`() = Unit - - @Test - @Case(VariantDataTestUnit::class) - fun `test AGPInterface#variantData`() = Unit - - @Test - @Case(OriginalApplicationIdTestUnit::class) - fun `test AGPInterface#originalApplicationId`() = Unit - - @Test - @Case(HasDynamicFeatureTestUnit::class) - fun `test AGPInterface#hasDynamicFeature`() = Unit - - @Test - @Case(RawAndroidResourcesTestUnit::class) - fun `test AGPInterface#rawAndroidResources`() = Unit - - @Test - @Case(AllArtifactsTestUnit::class) - fun `test AGPInterface#allArtifacts`() = Unit - - @Test - @Case(MinSdkVersionTestUnit::class) - fun `test AGPInterface#minSdkVersion`() = Unit - - @Test - @Case(TargetSdkVersionTestUnit::class) - fun `test AGPInterface#targetSdkVersion`() = Unit - - @Test - @Case(AarTestUnit::class) - fun `test AGPInterface#aar`() = Unit - - @Test - @Case(ApkTestUnit::class) - fun `test AGPInterface#apk`() = Unit - - @Test - @Case(MergedManifestsTestUnit::class) - fun `test AGPInterface#mergedManifests`() = Unit - - @Test - @Case(MergedResourcesTestUnit::class) - fun `test AGPInterface#mergedRes`() = Unit - - @Test - @Case(MergedAssetsTestUnit::class) - fun `test AGPInterface#mergedAssets`() = Unit - - @Test - @Case(ProcessedResTestUnit::class) - fun `test AGPInterface#processedRes`() = Unit - - @Test - @Case(SymbolListTestUnit::class) - fun `test AGPInterface#symbolList`() = Unit - - @Test - @Case(SymbolListWithPackageNameTestUnit::class) - fun `test AGPInterface#symbolListWithPackageName`() = Unit - - @Test - @Case(AllClassesTestUnit::class) - fun `test AGPInterface#allClasses`() = Unit - - @Test - @Case(BuildToolsTestUnit::class) - fun `test AGPInterface#buildTools`() = Unit - -} - -class V33AppIntegrationTest : V33IntegrationTest(false) - -class V33LibIntegrationTest : V33IntegrationTest(true) - -class ScopeFullWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("PROJECT,SUB_PROJECTS,EXTERNAL_LIBRARIES,FEATURES", AGP.scopeFullWithFeatures.joinToString(",")) - } -} - -class ScopeFullLibraryWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("FEATURES,PROJECT", AGP.scopeFullLibraryWithFeatures.joinToString(",")) - } -} - -class ProjectTest : TestCase { - override fun apply(project: Project) { - val assert: (BaseVariant) -> Unit = { variant -> - assertEquals(project, AGP.run { variant.project }) - } - project.afterEvaluate { - when (val android = project.getAndroid()) { - is AppExtension -> android.applicationVariants.forEach(assert) - is LibraryExtension -> android.libraryVariants.forEach(assert) - } - } - } -} - -class JavaCompilerTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.javaCompilerTask }) - } -} - -class PreBuildTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.preBuildTask }) - } -} - -class AssembleTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.assembleTask }) - } -} - -class MergeAssetsTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeAssetsTask }) - } -} - -class MergeResourcesTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeResourcesTask }) - } -} - -class GetTaskNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("assemble${variant.name.capitalize()}", AGP.run { variant.getTaskName("assemble") }) - } -} - - -class GetTaskName2TestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("merge${variant.name.capitalize()}Resources", AGP.run { variant.getTaskName("merge", "Resources") }) - } -} - -class VariantDataTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.variantData }) - } -} - -class OriginalApplicationIdTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.originalApplicationId }) - } -} - -class HasDynamicFeatureTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertFalse(AGP.run { variant.hasDynamicFeature }) - } -} - -class RawAndroidResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val rawAndroidResources = AGP.run { variant.rawAndroidResources } - assertNotNull(rawAndroidResources) - if (rawAndroidResources.isEmpty()) { - fail("rawAndroidResources is empty") - } - rawAndroidResources.forEach { - println(" - ${it.path}") - } - } - } -} - -class AllArtifactsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val allArtifacts = AGP.run { variant.allArtifacts } - assertNotNull(allArtifacts) - if (allArtifacts.isEmpty()) { - fail("allArtifacts is empty") - } - allArtifacts.forEach { (k, v) -> - println(" - $k => $v") - } - } - } -} - -class MinSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val minSdkVersion = AGP.run { variant.minSdkVersion } - assertNotNull(minSdkVersion) - assertEquals(MIN_SDK_VERSION, minSdkVersion.apiLevel) - } -} - -class TargetSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val targetSdkVersion = AGP.run { variant.targetSdkVersion } - assertNotNull(targetSdkVersion) - assertEquals(TARGET_SDK_VERSION, targetSdkVersion.apiLevel) - } -} - -class AarTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.library")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val aar = AGP.run { variant.aar }.search { - it.extension == "aar" - } - if (aar.isEmpty()) { - fail("aar is empty") - } - aar.forEach { - println(" - ${it.path}") - } - } - } -} - -class ApkTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val apk = AGP.run { variant.apk }.search { - it.extension == "apk" - } - if (apk.isEmpty()) { - fail("apk is empty") - } - apk.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedManifestsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedManifests = AGP.run { variant.mergedManifests }.search { - it.name == "AndroidManifest.xml" - } - if (mergedManifests.isEmpty()) { - fail("mergedManifests is empty") - } - mergedManifests.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedResources = AGP.run { variant.mergedRes } - if (mergedResources.isEmpty()) { - fail("mergedRes is empty") - } - mergedResources.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedAssetsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedAssets = AGP.run { variant.mergedAssets } - if (mergedAssets.isEmpty()) { - fail("mergedAssets is empty") - } - mergedAssets.forEach { - println(" - ${it.path}") - } - } - } -} - -class ProcessedResTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val processedRes = AGP.run { variant.processedRes }.search { - it.extension == "ap_" - } - if (processedRes.isEmpty()) { - fail("processedRes is empty") - } - processedRes.forEach { - println(" - ${it.path}") - } - } - } -} - -class SymbolListTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val symbolList = AGP.run { variant.symbolList } - if (symbolList.isEmpty()) { - fail("symbolList is empty") - } - symbolList.forEach { - println(" - ${it.path}") - } - } - } -} - -class SymbolListWithPackageNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val symbolListWithPackageName = AGP.run { variant.symbolListWithPackageName } - if (symbolListWithPackageName.isEmpty()) { - fail("symbolListWithPackageName is empty") - } - symbolListWithPackageName.forEach { - println(" - ${it.path}") - } - } - } -} - -class AllClassesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val location = AGP.run { variant.allClasses }.files - assertTrue("ALL_CLASSES: $location", location::isNotEmpty) - assertTrue("No class file found at $location") { - location.search(File::isFile).isNotEmpty() - } - } - } -} - -class BuildToolsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val buildTools = AGP.run { variant.buildTools } - assertNotNull(buildTools) - BuildToolInfo.PathId.values().map { - it.name to buildTools.getPath(it) - }.forEach { (k, v) -> - println(" - $k => $v") - } - } -} diff --git a/booster-android-gradle-v3_3/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_3/V33.kt b/booster-android-gradle-v3_3/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_3/V33.kt deleted file mode 100644 index 592165acb..000000000 --- a/booster-android-gradle-v3_3/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_3/V33.kt +++ /dev/null @@ -1,253 +0,0 @@ -package com.didiglobal.booster.android.gradle.v3_3 - -import com.android.build.api.artifact.ArtifactType -import com.android.build.api.artifact.BuildArtifactType -import com.android.build.api.transform.Context -import com.android.build.api.transform.QualifiedContent -import com.android.build.gradle.api.ApplicationVariant -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.LibraryVariant -import com.android.build.gradle.internal.api.artifact.SourceArtifactType -import com.android.build.gradle.internal.pipeline.TransformManager -import com.android.build.gradle.internal.pipeline.TransformTask -import com.android.build.gradle.internal.publishing.AndroidArtifacts -import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactScope -import com.android.build.gradle.internal.scope.AnchorOutputType -import com.android.build.gradle.internal.scope.GlobalScope -import com.android.build.gradle.internal.scope.InternalArtifactType -import com.android.build.gradle.internal.scope.VariantScope -import com.android.build.gradle.internal.variant.BaseVariantData -import com.android.builder.core.VariantType -import com.android.builder.model.AndroidProject -import com.android.builder.model.ApiVersion -import com.android.sdklib.BuildToolInfo -import com.didiglobal.booster.gradle.AGPInterface -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.artifacts.ArtifactCollection -import org.gradle.api.artifacts.component.ComponentIdentifier -import org.gradle.api.artifacts.result.ResolvedArtifactResult -import org.gradle.api.artifacts.result.ResolvedDependencyResult -import org.gradle.api.file.FileCollection -import org.gradle.api.tasks.TaskProvider -import java.io.File -import java.util.TreeMap - -@Suppress("UnstableApiUsage") -private val ARTIFACT_TYPES = arrayOf>( - AnchorOutputType.values(), - BuildArtifactType.values(), - SourceArtifactType.values(), - InternalArtifactType.values() -).flatten().associateBy(ArtifactType::name) - -internal object V33 : AGPInterface { - - @Suppress("UnstableApiUsage") - private fun BaseVariant.getFinalArtifactFiles(type: ArtifactType): FileCollection { - return try { - variantScope.artifacts.getFinalArtifactFiles(type).get() - } catch (e: Throwable) { - project.logger.warn(e.message, e) - project.files() - } - } - - override val scopeFullWithFeatures: MutableSet - get() = TransformManager.SCOPE_FULL_WITH_FEATURES - - override val scopeFullLibraryWithFeatures: MutableSet - get() = (TransformManager.SCOPE_FEATURES + QualifiedContent.Scope.PROJECT).toMutableSet() - - override val BaseVariant.project: Project - get() = globalScope.project - - override val BaseVariant.javaCompilerTaskProvider: TaskProvider - get() = javaCompileProvider - - override val BaseVariant.preBuildTaskProvider: TaskProvider - get() = preBuildProvider - - override val BaseVariant.assembleTaskProvider: TaskProvider - get() = assembleProvider - - override val BaseVariant.mergeAssetsTaskProvider: TaskProvider - get() = mergeAssetsProvider - - override val BaseVariant.mergeResourcesTaskProvider: TaskProvider - get() = mergeResourcesProvider - - override val BaseVariant.mergeNativeLibsTaskProvider: TaskProvider - get() = @Suppress("DEPRECATION") project.tasks.named("transformNativeLibsWithMergeJniLibsFor${name.capitalize()}") - - override val BaseVariant.processJavaResourcesTaskProvider: TaskProvider - get() = processJavaResourcesProvider - - override fun BaseVariant.getTaskName(prefix: String): String { - return variantScope.getTaskName(prefix) - } - - override fun BaseVariant.getTaskName(prefix: String, suffix: String): String { - return variantScope.getTaskName(prefix, suffix) - } - - override val BaseVariant.variantData: BaseVariantData - get() = javaClass.getDeclaredMethod("getVariantData").apply { - isAccessible = true - }.invoke(this) as BaseVariantData - - val BaseVariant.variantScope: VariantScope - get() = variantData.scope - - private val BaseVariant.globalScope: GlobalScope - get() = variantScope.globalScope - - override val BaseVariant.originalApplicationId: String - get() = variantData.variantConfiguration.originalApplicationId - - override val BaseVariant.hasDynamicFeature: Boolean - get() = globalScope.hasDynamicFeatures() - - override val BaseVariant.rawAndroidResources: FileCollection - get() = variantData.allRawAndroidResources - - override val BaseVariant.localAndroidResources: FileCollection - get() = variantData.androidResources.values.map { - it.get() - }.reduce { collection, file -> - collection.plus(file) - } - - override fun BaseVariant.getArtifactCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): ArtifactCollection { - return variantScope.getArtifactCollection(configType, scope, artifactType) - } - - override fun BaseVariant.getArtifactFileCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): FileCollection { - return variantScope.getArtifactFileCollection(configType, scope, artifactType) - } - - override val BaseVariant.allArtifacts: Map - get() = ARTIFACT_TYPES.entries.associateTo(TreeMap()) { (name, type) -> - val artifacts: FileCollection by lazy { - getFinalArtifactFiles(type) - } - name to artifacts - } - - override val BaseVariant.minSdkVersion: ApiVersion - get() = variantData.variantConfiguration.minSdkVersion.let { minSdkVersion -> - object : ApiVersion { - override fun getApiLevel(): Int = minSdkVersion.apiLevel - override fun getCodename(): String? = minSdkVersion.codename - override fun getApiString(): String = minSdkVersion.apiString - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is ApiVersion) return false - return apiLevel == other.apiLevel || codename.equals(other.codename, false) - } - - override fun hashCode(): Int = codename?.hashCode() ?: apiLevel - } - } - - override val BaseVariant.targetSdkVersion: ApiVersion - get() = variantData.variantConfiguration.targetSdkVersion - - private val BaseVariant.variantType: VariantType - get() = variantScope.type - - override val BaseVariant.isApplication: Boolean - get() = variantType.isApk - - override val BaseVariant.isLibrary: Boolean - get() = variantType.isAar - - override val BaseVariant.isDynamicFeature: Boolean - get() = variantType.isDynamicFeature - - override val BaseVariant.aar: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.AAR) - - override val BaseVariant.apk: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.APK) - - override val BaseVariant.mergedManifests: FileCollection - get() = getFinalArtifactFiles(when (this) { - is ApplicationVariant -> InternalArtifactType.MERGED_MANIFESTS - is LibraryVariant -> InternalArtifactType.LIBRARY_MANIFEST - else -> TODO("Unsupported variant type: $name") - }) - - override val BaseVariant.mergedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.MERGED_RES) - - override val BaseVariant.mergedNativeLibs: FileCollection - get() = project.files("build${File.separatorChar}${AndroidProject.FD_INTERMEDIATES}${File.separatorChar}transforms${File.separatorChar}mergeJniLibs${File.separatorChar}$name") - - override val BaseVariant.mergedAssets: FileCollection - get() = getFinalArtifactFiles(when (this) { - is ApplicationVariant -> InternalArtifactType.MERGED_ASSETS - is LibraryVariant -> InternalArtifactType.LIBRARY_ASSETS - else -> TODO("Unsupported variant type: $variantType") - }) - - override val BaseVariant.processedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.PROCESSED_RES) - - override val BaseVariant.symbolList: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.SYMBOL_LIST) - - override val BaseVariant.symbolListWithPackageName: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.SYMBOL_LIST_WITH_PACKAGE_NAME) - - override val BaseVariant.dataBindingDependencyArtifacts: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.DATA_BINDING_DEPENDENCY_ARTIFACTS) - - override val BaseVariant.allClasses: FileCollection - get() = getFinalArtifactFiles(AnchorOutputType.ALL_CLASSES) - - override val BaseVariant.buildTools: BuildToolInfo - get() = globalScope.androidBuilder.buildToolInfo - - override val BaseVariant.isPrecompileDependenciesResourcesEnabled: Boolean - get() = false - - override fun BaseVariant.getDependencies(transitive: Boolean, filter: (ComponentIdentifier) -> Boolean): Collection { - val all = listOf(AndroidArtifacts.ArtifactType.AAR, AndroidArtifacts.ArtifactType.JAR) - .asSequence() - .map { - getArtifactCollection(AndroidArtifacts.ConsumedConfigType.RUNTIME_CLASSPATH, ArtifactScope.ALL, it).filter { result -> - filter(result.id.componentIdentifier) - } - } - .flatten() - .associateBy { - it.id.componentIdentifier.displayName - } - val result = if (!transitive) { - runtimeConfiguration.incoming.resolutionResult.root.dependencies.filterIsInstance().mapNotNull { - it.selected.id.displayName.takeIf { id -> id in all.keys } - }.associateWith { - all[it]!! - } - } else { - all - } - return result.values.toSet() - } - - override val Context.task: TransformTask - get() = this as TransformTask - - override val Project.aapt2Enabled: Boolean - get() = true - -} diff --git a/booster-android-gradle-v3_3/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_3/V33Factory.kt b/booster-android-gradle-v3_3/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_3/V33Factory.kt deleted file mode 100644 index 732d3e4cd..000000000 --- a/booster-android-gradle-v3_3/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_3/V33Factory.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.didiglobal.booster.android.gradle.v3_3 - -import com.android.repository.Revision -import com.didiglobal.booster.gradle.AGPInterface -import com.didiglobal.booster.gradle.AGPInterfaceFactory -import com.google.auto.service.AutoService - -@AutoService(AGPInterfaceFactory::class) -class V33Factory : AGPInterfaceFactory { - - override val revision: Revision = Revision(3, 3, 0) - - override fun newAGPInterface(): AGPInterface = V33 - -} diff --git a/booster-android-gradle-v3_4/build.gradle b/booster-android-gradle-v3_4/build.gradle deleted file mode 100644 index 686414cbe..000000000 --- a/booster-android-gradle-v3_4/build.gradle +++ /dev/null @@ -1,19 +0,0 @@ -apply plugin: 'java-gradle-plugin' - -apply from: "$rootDir/gradle/booster.gradle" -apply from: "$rootDir/gradle/integration-test.gradle" -apply from: "$rootDir/gradle/functional-test.gradle" - -dependencies { - kapt 'com.google.auto.service:auto-service:1.0' - api 'com.google.auto.service:auto-service:1.0' - api project(':booster-android-gradle-compat') - compileOnly 'com.android.tools.build:gradle:3.4.0' - testImplementation 'com.android.tools.build:gradle:3.4.0' - testImplementation 'io.bootstage.testkit:testkit-gradle-plugin:1.4.0' - testImplementation project(':booster-build') -} - -gradlePlugin { - testSourceSets sourceSets.functionalTest, sourceSets.integrationTest -} \ No newline at end of file diff --git a/booster-android-gradle-v3_4/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v3_4/V34IntegrationTest.kt b/booster-android-gradle-v3_4/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v3_4/V34IntegrationTest.kt deleted file mode 100644 index 6c20bf1a5..000000000 --- a/booster-android-gradle-v3_4/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v3_4/V34IntegrationTest.kt +++ /dev/null @@ -1,475 +0,0 @@ -@file:Suppress("DEPRECATION") - -package com.didiglobal.booster.android.gradle.v3_4 - -import com.android.build.gradle.AppExtension -import com.android.build.gradle.BaseExtension -import com.android.build.gradle.LibraryExtension -import com.android.build.gradle.api.BaseVariant -import com.android.sdklib.BuildToolInfo -import com.didiglobal.booster.gradle.AGP -import com.didiglobal.booster.gradle.getAndroid -import com.didiglobal.booster.kotlinx.search -import io.bootstage.testkit.gradle.Case -import io.bootstage.testkit.gradle.TestCase -import io.bootstage.testkit.gradle.VariantTestCase -import io.bootstage.testkit.gradle.rules.GradleExecutor -import io.bootstage.testkit.gradle.rules.LocalProperties -import io.bootstage.testkit.gradle.rules.copyFromResource -import io.bootstage.testkit.gradle.rules.rule -import org.gradle.api.Project -import org.junit.Before -import org.junit.Rule -import org.junit.rules.TemporaryFolder -import org.junit.rules.TestRule -import java.io.File -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertNotNull -import kotlin.test.assertTrue -import kotlin.test.fail - -private val MIN_SDK_VERSION = System.getProperty("android.minsdk.version").toInt() - -private const val TARGET_SDK_VERSION = 26 - -private val ARGS = System.getProperty("gradle.args").split("\\s+".toRegex()) + listOf( - "-Pbooster_version=${Build.VERSION}", - "-Pandroid_gradle_version=3.4.0", - "-Pcompile_sdk_version=28", - "-Pbuild_tools_version=26.0.3", - "-Pmin_sdk_version=${MIN_SDK_VERSION}", - "-Ptarget_sdk_version=${TARGET_SDK_VERSION}" -) - -@Suppress("RemoveCurlyBracesFromTemplate", "FunctionName") -abstract class V34IntegrationTest(private val isLib: Boolean) { - - private val projectDir = TemporaryFolder() - - @get:Rule - val ruleChain: TestRule = rule(projectDir) { - rule(LocalProperties(projectDir::getRoot)) { - GradleExecutor(projectDir::getRoot, "5.1.1", *ARGS.toTypedArray()) - } - } - - @Before - fun setup() { - projectDir.copyFromResource("${if (isLib) "lib" else "app"}.gradle", "build.gradle") - projectDir.copyFromResource("buildSrc") - projectDir.copyFromResource("src") - projectDir.newFile("gradle.properties").writeText("org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=2g") - assertEquals(3, AGP.revision.major) - assertEquals(4, AGP.revision.minor) - } - - @Test - @Case(ScopeFullWithFeaturesTest::class) - fun `test AGPInterface#scopeFullWithFeatures`() = Unit - - @Test - @Case(ScopeFullLibraryWithFeaturesTest::class) - fun `test AGPInterface#scopeFullLibraryWithFeatures`() = Unit - - @Test - @Case(ProjectTest::class) - fun `test AGPInterface#project`() = Unit - - @Test - @Case(JavaCompilerTaskTestUnit::class) - fun `test AGPInterface#javaCompilerTask`() = Unit - - @Test - @Case(PreBuildTaskTestUnit::class) - fun `test AGPInterface#preBuildTask`() = Unit - - @Test - @Case(AssembleTaskTestUnit::class) - fun `test AGPInterface#assembleTask`() = Unit - - @Test - @Case(MergeAssetsTaskTestUnit::class) - fun `test AGPInterface#mergeAssetsTask`() = Unit - - @Test - @Case(MergeResourcesTaskTestUnit::class) - fun `test AGPInterface#mergeResources`() = Unit - - @Test - @Case(GetTaskNameTestUnit::class) - fun `test AGPInterface#getTaskName(String)`() = Unit - - @Test - @Case(GetTaskName2TestUnit::class) - fun `test AGPInterface#getTaskName(String, String)`() = Unit - - @Test - @Case(VariantDataTestUnit::class) - fun `test AGPInterface#variantData`() = Unit - - @Test - @Case(OriginalApplicationIdTestUnit::class) - fun `test AGPInterface#originalApplicationId`() = Unit - - @Test - @Case(HasDynamicFeatureTestUnit::class) - fun `test AGPInterface#hasDynamicFeature`() = Unit - - @Test - @Case(RawAndroidResourcesTestUnit::class) - fun `test AGPInterface#rawAndroidResources`() = Unit - - @Test - @Case(AllArtifactsTestUnit::class) - fun `test AGPInterface#allArtifacts`() = Unit - - @Test - @Case(MinSdkVersionTestUnit::class) - fun `test AGPInterface#minSdkVersion`() = Unit - - @Test - @Case(TargetSdkVersionTestUnit::class) - fun `test AGPInterface#targetSdkVersion`() = Unit - - @Test - @Case(AarTestUnit::class) - fun `test AGPInterface#aar`() = Unit - - @Test - @Case(ApkTestUnit::class) - fun `test AGPInterface#apk`() = Unit - - @Test - @Case(MergedManifestsTestUnit::class) - fun `test AGPInterface#mergedManifests`() = Unit - - @Test - @Case(MergedResourcesTestUnit::class) - fun `test AGPInterface#mergedRes`() = Unit - - @Test - @Case(MergedAssetsTestUnit::class) - fun `test AGPInterface#mergedAssets`() = Unit - - @Test - @Case(ProcessedResTestUnit::class) - fun `test AGPInterface#processedRes`() = Unit - - @Test - @Case(SymbolListTestUnit::class) - fun `test AGPInterface#symbolList`() = Unit - - @Test - @Case(SymbolListWithPackageNameTestUnit::class) - fun `test AGPInterface#symbolListWithPackageName`() = Unit - - @Test - @Case(AllClassesTestUnit::class) - fun `test AGPInterface#allClasses`() = Unit - - @Test - @Case(BuildToolsTestUnit::class) - fun `test AGPInterface#buildTools`() = Unit - -} - -class V34AppIntegrationTest : V34IntegrationTest(false) - -class V34LibIntegrationTest : V34IntegrationTest(true) - -class ScopeFullWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("PROJECT,SUB_PROJECTS,EXTERNAL_LIBRARIES,FEATURES", AGP.scopeFullWithFeatures.joinToString(",")) - } -} - -class ScopeFullLibraryWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("FEATURES,PROJECT", AGP.scopeFullLibraryWithFeatures.joinToString(",")) - } -} - -class ProjectTest : TestCase { - override fun apply(project: Project) { - val assert: (BaseVariant) -> Unit = { variant -> - assertEquals(project, AGP.run { variant.project }) - } - project.afterEvaluate { - when (val android = project.getAndroid()) { - is AppExtension -> android.applicationVariants.forEach(assert) - is LibraryExtension -> android.libraryVariants.forEach(assert) - } - } - } -} - -class JavaCompilerTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.javaCompilerTask }) - } -} - -class PreBuildTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.preBuildTask }) - } -} - -class AssembleTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.assembleTask }) - } -} - -class MergeAssetsTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeAssetsTask }) - } -} - -class MergeResourcesTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeResourcesTask }) - } -} - -class GetTaskNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("assemble${variant.name.capitalize()}", AGP.run { variant.getTaskName("assemble") }) - } -} - - -class GetTaskName2TestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("merge${variant.name.capitalize()}Resources", AGP.run { variant.getTaskName("merge", "Resources") }) - } -} - -class VariantDataTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.variantData }) - } -} - -class OriginalApplicationIdTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.originalApplicationId }) - } -} - -class HasDynamicFeatureTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertFalse(AGP.run { variant.hasDynamicFeature }) - } -} - -class RawAndroidResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val rawAndroidResources = AGP.run { variant.rawAndroidResources } - assertNotNull(rawAndroidResources) - if (rawAndroidResources.isEmpty()) { - fail("rawAndroidResources is empty") - } - rawAndroidResources.forEach { - println(" - ${it.path}") - } - } - } -} - -class AllArtifactsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val allArtifacts = AGP.run { variant.allArtifacts } - assertNotNull(allArtifacts) - if (allArtifacts.isEmpty()) { - fail("allArtifacts is empty") - } - allArtifacts.forEach { (k, v) -> - println(" - $k => $v") - } - } - } -} - -class MinSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val minSdkVersion = AGP.run { variant.minSdkVersion } - assertNotNull(minSdkVersion) - assertEquals(MIN_SDK_VERSION, minSdkVersion.apiLevel) - } -} - -class TargetSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val targetSdkVersion = AGP.run { variant.targetSdkVersion } - assertNotNull(targetSdkVersion) - assertEquals(TARGET_SDK_VERSION, targetSdkVersion.apiLevel) - } -} - -class AarTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.library")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val aar = AGP.run { variant.aar }.search { - it.extension == "aar" - } - if (aar.isEmpty()) { - fail("aar is empty") - } - aar.forEach { - println(" - ${it.path}") - } - } - } -} - -class ApkTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val apk = AGP.run { variant.apk }.search { - it.extension == "apk" - } - if (apk.isEmpty()) { - fail("apk is empty") - } - apk.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedManifestsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedManifests = AGP.run { variant.mergedManifests }.search { - it.name == "AndroidManifest.xml" - } - if (mergedManifests.isEmpty()) { - fail("mergedManifests is empty") - } - mergedManifests.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedResources = AGP.run { variant.mergedRes } - if (mergedResources.isEmpty()) { - fail("mergedRes is empty") - } - mergedResources.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedAssetsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedAssets = AGP.run { variant.mergedAssets } - if (mergedAssets.isEmpty()) { - fail("mergedAssets is empty") - } - mergedAssets.forEach { - println(" - ${it.path}") - } - } - } -} - -class ProcessedResTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val processedRes = AGP.run { variant.processedRes }.search { - it.extension == "ap_" - } - if (processedRes.isEmpty()) { - fail("processedRes is empty") - } - processedRes.forEach { - println(" - ${it.path}") - } - } - } -} - -class SymbolListTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val symbolList = AGP.run { variant.symbolList } - if (symbolList.isEmpty()) { - fail("symbolList is empty") - } - symbolList.forEach { - println(" - ${it.path}") - } - } - } -} - -class SymbolListWithPackageNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val symbolListWithPackageName = AGP.run { variant.symbolListWithPackageName } - if (symbolListWithPackageName.isEmpty()) { - fail("symbolListWithPackageName is empty") - } - symbolListWithPackageName.forEach { - println(" - ${it.path}") - } - } - } -} - -class AllClassesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val location = AGP.run { variant.allClasses }.files - assertTrue("ALL_CLASSES: $location", location::isNotEmpty) - assertTrue("No class file found at $location") { - location.search(File::isFile).isNotEmpty() - } - } - } -} - -class BuildToolsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val buildTools = AGP.run { variant.buildTools } - assertNotNull(buildTools) - BuildToolInfo.PathId.values().map { - it.name to buildTools.getPath(it) - }.forEach { (k, v) -> - println(" - $k => $v") - } - } -} diff --git a/booster-android-gradle-v3_4/src/integrationTest/resources/app.gradle b/booster-android-gradle-v3_4/src/integrationTest/resources/app.gradle deleted file mode 100644 index aa3c5f2d6..000000000 --- a/booster-android-gradle-v3_4/src/integrationTest/resources/app.gradle +++ /dev/null @@ -1,60 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } - dependencies { - classpath "com.android.tools.build:gradle:${project.android_gradle_version}" - classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { - exclude group: 'com.google.guava' - } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" - } -} - -apply plugin: 'com.android.application' -apply plugin: 'com.didiglobal.booster' -apply plugin: 'io.bootstage.testkit' - -android { - compileSdkVersion project.compile_sdk_version as Integer - buildToolsVersion project.build_tools_version - defaultConfig { - applicationId 'com.didiglobal.booster.test' - minSdkVersion project.min_sdk_version as Integer - targetSdkVersion project.target_sdk_version as Integer - versionCode 1 - versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - buildTypes { - debug { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - flavorDimensions 'lang' - productFlavors { - en { - dimension 'lang' - applicationIdSuffix '.en' - } - cn { - dimension 'lang' - applicationIdSuffix '.cn' - } - } - lintOptions { - checkReleaseBuilds false - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} diff --git a/booster-android-gradle-v3_4/src/integrationTest/resources/buildSrc/build.gradle b/booster-android-gradle-v3_4/src/integrationTest/resources/buildSrc/build.gradle deleted file mode 100644 index 79a9b104a..000000000 --- a/booster-android-gradle-v3_4/src/integrationTest/resources/buildSrc/build.gradle +++ /dev/null @@ -1,24 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} - -dependencies { - implementation "com.android.tools.build:gradle:${project.android_gradle_version}" - implementation("com.didiglobal.booster:booster-android-gradle-api:${project.booster_version}") { - exclude group: 'com.google.guava' - } - implementation "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" -} diff --git a/booster-android-gradle-v3_4/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_4/V34.kt b/booster-android-gradle-v3_4/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_4/V34.kt deleted file mode 100644 index dc1ad351d..000000000 --- a/booster-android-gradle-v3_4/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_4/V34.kt +++ /dev/null @@ -1,255 +0,0 @@ -package com.didiglobal.booster.android.gradle.v3_4 - -import com.android.build.api.artifact.ArtifactType -import com.android.build.api.artifact.BuildArtifactType -import com.android.build.api.transform.Context -import com.android.build.api.transform.QualifiedContent -import com.android.build.gradle.AppPlugin -import com.android.build.gradle.DynamicFeaturePlugin -import com.android.build.gradle.LibraryPlugin -import com.android.build.gradle.api.ApplicationVariant -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.LibraryVariant -import com.android.build.gradle.internal.api.artifact.SourceArtifactType -import com.android.build.gradle.internal.pipeline.TransformManager -import com.android.build.gradle.internal.pipeline.TransformTask -import com.android.build.gradle.internal.publishing.AndroidArtifacts -import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactScope -import com.android.build.gradle.internal.scope.AnchorOutputType -import com.android.build.gradle.internal.scope.GlobalScope -import com.android.build.gradle.internal.scope.InternalArtifactType -import com.android.build.gradle.internal.scope.VariantScope -import com.android.build.gradle.internal.scope.getOutputDir -import com.android.build.gradle.internal.variant.BaseVariantData -import com.android.builder.core.VariantType -import com.android.builder.model.AndroidProject -import com.android.builder.model.ApiVersion -import com.android.sdklib.BuildToolInfo -import com.didiglobal.booster.gradle.AGPInterface -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.artifacts.ArtifactCollection -import org.gradle.api.artifacts.component.ComponentIdentifier -import org.gradle.api.artifacts.result.ResolvedArtifactResult -import org.gradle.api.artifacts.result.ResolvedDependencyResult -import org.gradle.api.file.FileCollection -import org.gradle.api.tasks.TaskProvider -import java.io.File -import java.util.TreeMap - -@Suppress("UnstableApiUsage") -private val ARTIFACT_TYPES = arrayOf>( - AnchorOutputType.values(), - BuildArtifactType.values(), - SourceArtifactType.values(), - InternalArtifactType.values() -).flatten().associateBy(ArtifactType::name) - -internal object V34 : AGPInterface { - - @Suppress("UnstableApiUsage") - private fun BaseVariant.getFinalArtifactFiles(type: ArtifactType): FileCollection { - return try { - variantScope.artifacts.getFinalArtifactFiles(type).get() - } catch (e: Throwable) { - project.logger.warn(e.message, e) - project.files() - } - } - - override val scopeFullWithFeatures: MutableSet - get() = TransformManager.SCOPE_FULL_WITH_FEATURES - - override val scopeFullLibraryWithFeatures: MutableSet - get() = (TransformManager.SCOPE_FEATURES + QualifiedContent.Scope.PROJECT).toMutableSet() - - override val BaseVariant.project: Project - get() = globalScope.project - - override val BaseVariant.javaCompilerTaskProvider: TaskProvider - get() = javaCompileProvider - - override val BaseVariant.preBuildTaskProvider: TaskProvider - get() = preBuildProvider - - override val BaseVariant.assembleTaskProvider: TaskProvider - get() = assembleProvider - - override val BaseVariant.mergeAssetsTaskProvider: TaskProvider - get() = mergeAssetsProvider - - override val BaseVariant.mergeResourcesTaskProvider: TaskProvider - get() = mergeResourcesProvider - - override val BaseVariant.mergeNativeLibsTaskProvider: TaskProvider - get() = @Suppress("DEPRECATION") project.tasks.named("transformNativeLibsWithMergeJniLibsFor${name.capitalize()}") - - override val BaseVariant.processJavaResourcesTaskProvider: TaskProvider - get() = processJavaResourcesProvider - - override fun BaseVariant.getTaskName(prefix: String): String { - return variantScope.getTaskName(prefix) - } - - override fun BaseVariant.getTaskName(prefix: String, suffix: String): String { - return variantScope.getTaskName(prefix, suffix) - } - - override val BaseVariant.variantData: BaseVariantData - get() = javaClass.getDeclaredMethod("getVariantData").apply { - isAccessible = true - }.invoke(this) as BaseVariantData - - val BaseVariant.variantScope: VariantScope - get() = variantData.scope - - private val BaseVariant.globalScope: GlobalScope - get() = variantScope.globalScope - - override val BaseVariant.originalApplicationId: String - get() = variantData.variantConfiguration.originalApplicationId - - override val BaseVariant.hasDynamicFeature: Boolean - get() = globalScope.hasDynamicFeatures() - - override val BaseVariant.rawAndroidResources: FileCollection - get() = variantData.allRawAndroidResources - - override val BaseVariant.localAndroidResources: FileCollection - get() = variantData.androidResources.values.map { - it.get() - }.reduce { collection, file -> - collection.plus(file) - } - - override fun BaseVariant.getArtifactCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): ArtifactCollection { - return variantScope.getArtifactCollection(configType, scope, artifactType) - } - - override fun BaseVariant.getArtifactFileCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): FileCollection { - return variantScope.getArtifactFileCollection(configType, scope, artifactType) - } - - override val BaseVariant.allArtifacts: Map - get() = ARTIFACT_TYPES.entries.associateTo(TreeMap()) { (name, type) -> - val artifacts: FileCollection by lazy { - getFinalArtifactFiles(type) - } - name to artifacts - } - - override val BaseVariant.minSdkVersion: ApiVersion - get() = variantData.variantConfiguration.minSdkVersion.let { minSdkVersion -> - object : ApiVersion { - override fun getApiLevel(): Int = minSdkVersion.apiLevel - override fun getCodename(): String? = minSdkVersion.codename - override fun getApiString(): String = minSdkVersion.apiString - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is ApiVersion) return false - return apiLevel == other.apiLevel || codename.equals(other.codename, false) - } - - override fun hashCode(): Int = codename?.hashCode() ?: apiLevel - } - } - - override val BaseVariant.targetSdkVersion: ApiVersion - get() = variantData.variantConfiguration.targetSdkVersion - - private val BaseVariant.variantType: VariantType - get() = variantScope.type - - override val BaseVariant.isApplication: Boolean - get() = project.plugins.hasPlugin(AppPlugin::class.java) - override val BaseVariant.isLibrary: Boolean - get() = project.plugins.hasPlugin(LibraryPlugin::class.java) - override val BaseVariant.isDynamicFeature: Boolean - get() = project.plugins.hasPlugin(DynamicFeaturePlugin::class.java) - - override val BaseVariant.aar: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.AAR) - - override val BaseVariant.apk: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.APK) - - override val BaseVariant.mergedManifests: FileCollection - get() = project.files(File(when (this) { - is ApplicationVariant -> InternalArtifactType.MERGED_MANIFESTS - is LibraryVariant -> InternalArtifactType.LIBRARY_MANIFEST - else -> TODO("Unsupported variant type: $variantType") - }.getOutputDir(project.buildDir), name)) - - override val BaseVariant.mergedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.MERGED_RES) - - override val BaseVariant.mergedNativeLibs: FileCollection - get() = project.files("build${File.separatorChar}${AndroidProject.FD_INTERMEDIATES}${File.separatorChar}transforms${File.separatorChar}mergeJniLibs${File.separatorChar}$name") - - override val BaseVariant.mergedAssets: FileCollection - get() = getFinalArtifactFiles(when (this) { - is ApplicationVariant -> InternalArtifactType.MERGED_ASSETS - is LibraryVariant -> InternalArtifactType.LIBRARY_ASSETS - else -> TODO("Unsupported variant type: $variantType") - }) - - override val BaseVariant.processedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.PROCESSED_RES) - - override val BaseVariant.symbolList: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.SYMBOL_LIST) - - override val BaseVariant.symbolListWithPackageName: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.SYMBOL_LIST_WITH_PACKAGE_NAME) - - override val BaseVariant.dataBindingDependencyArtifacts: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.DATA_BINDING_DEPENDENCY_ARTIFACTS) - - override val BaseVariant.allClasses: FileCollection - get() = getFinalArtifactFiles(AnchorOutputType.ALL_CLASSES) - - override val BaseVariant.buildTools: BuildToolInfo - get() = globalScope.androidBuilder.buildToolInfo - - override val BaseVariant.isPrecompileDependenciesResourcesEnabled: Boolean - get() = false - - override fun BaseVariant.getDependencies(transitive: Boolean, filter: (ComponentIdentifier) -> Boolean): Collection { - val all = listOf(AndroidArtifacts.ArtifactType.AAR, AndroidArtifacts.ArtifactType.JAR) - .asSequence() - .map { - getArtifactCollection(AndroidArtifacts.ConsumedConfigType.RUNTIME_CLASSPATH, ArtifactScope.ALL, it).filter { result -> - filter(result.id.componentIdentifier) - } - } - .flatten() - .associateBy { - it.id.componentIdentifier.displayName - } - val result = if (!transitive) { - runtimeConfiguration.incoming.resolutionResult.root.dependencies.filterIsInstance().mapNotNull { - it.selected.id.displayName.takeIf { id -> id in all.keys } - }.associateWith { - all[it]!! - } - } else { - all - } - return result.values.toSet() - } - - override val Context.task: TransformTask - get() = this as TransformTask - - override val Project.aapt2Enabled: Boolean - get() = true - -} diff --git a/booster-android-gradle-v3_5/README.md b/booster-android-gradle-v3_5/README.md deleted file mode 100644 index 77ebfe5ec..000000000 --- a/booster-android-gradle-v3_5/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# booster-android-gradle-v3_5 - -This module is an implementation of [booster-android-gradle-api](../booster-android-gradle-api) for Android gradle plugin above 3.5. - -本模块是 [booster-android-gradle-api](../booster-android-gradle-api) 针对 Android gradle plugin 3.5 以上版本的实现。 - diff --git a/booster-android-gradle-v3_5/build.gradle b/booster-android-gradle-v3_5/build.gradle deleted file mode 100644 index 4084399d0..000000000 --- a/booster-android-gradle-v3_5/build.gradle +++ /dev/null @@ -1,19 +0,0 @@ -apply plugin: 'java-gradle-plugin' - -apply from: "$rootDir/gradle/booster.gradle" -apply from: "$rootDir/gradle/integration-test.gradle" -apply from: "$rootDir/gradle/functional-test.gradle" - -dependencies { - kapt 'com.google.auto.service:auto-service:1.0' - api 'com.google.auto.service:auto-service:1.0' - api project(':booster-android-gradle-compat') - compileOnly 'com.android.tools.build:gradle:3.5.0' - testImplementation 'com.android.tools.build:gradle:3.5.0' - testImplementation 'io.bootstage.testkit:testkit-gradle-plugin:1.4.0' - testImplementation project(':booster-build') -} - -gradlePlugin { - testSourceSets sourceSets.functionalTest, sourceSets.integrationTest -} \ No newline at end of file diff --git a/booster-android-gradle-v3_5/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v3_5/V35IntegrationTest.kt b/booster-android-gradle-v3_5/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v3_5/V35IntegrationTest.kt deleted file mode 100644 index dd19ade8e..000000000 --- a/booster-android-gradle-v3_5/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v3_5/V35IntegrationTest.kt +++ /dev/null @@ -1,476 +0,0 @@ -@file:Suppress("DEPRECATION") - -package com.didiglobal.booster.android.gradle.v3_5 - -import com.android.build.gradle.AppExtension -import com.android.build.gradle.BaseExtension -import com.android.build.gradle.LibraryExtension -import com.android.build.gradle.api.BaseVariant -import com.android.sdklib.BuildToolInfo -import com.didiglobal.booster.gradle.AGP -import com.didiglobal.booster.gradle.getAndroid -import com.didiglobal.booster.kotlinx.search -import io.bootstage.testkit.gradle.Case -import io.bootstage.testkit.gradle.TestCase -import io.bootstage.testkit.gradle.VariantTestCase -import io.bootstage.testkit.gradle.rules.GradleExecutor -import io.bootstage.testkit.gradle.rules.LocalProperties -import io.bootstage.testkit.gradle.rules.copyFromResource -import io.bootstage.testkit.gradle.rules.rule -import org.gradle.api.Project -import org.junit.Before -import org.junit.Rule -import org.junit.rules.TemporaryFolder -import org.junit.rules.TestRule -import java.io.File -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertNotNull -import kotlin.test.assertTrue -import kotlin.test.fail - -private val MIN_SDK_VERSION = System.getProperty("android.minsdk.version").toInt() - -private const val TARGET_SDK_VERSION = 26 - -private val ARGS = System.getProperty("gradle.args").split("\\s+".toRegex()) + listOf( - "-Pbooster_version=${Build.VERSION}", - "-Pandroid_gradle_version=3.5.0", - "-Pcompile_sdk_version=28", - "-Pbuild_tools_version=26.0.3", - "-Pmin_sdk_version=${MIN_SDK_VERSION}", - "-Ptarget_sdk_version=${TARGET_SDK_VERSION}", -) - -@Suppress("RemoveCurlyBracesFromTemplate", "FunctionName") -abstract class V35IntegrationTest(private val isLib: Boolean) { - - private val projectDir = TemporaryFolder() - - @get:Rule - val ruleChain: TestRule = rule(projectDir) { - rule(LocalProperties(projectDir::getRoot)) { - GradleExecutor(projectDir::getRoot, "5.4.1", *ARGS.toTypedArray()) - } - } - - @Before - fun setup() { - projectDir.copyFromResource("${if (isLib) "lib" else "app"}.gradle", "build.gradle") - projectDir.copyFromResource("buildSrc") - projectDir.copyFromResource("src") - projectDir.newFile("gradle.properties").writeText("org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=2g") - assertEquals(3, AGP.revision.major) - assertEquals(5, AGP.revision.minor) - } - - @Test - @Case(ScopeFullWithFeaturesTest::class) - fun `test AGPInterface#scopeFullWithFeatures`() = Unit - - @Test - @Case(ScopeFullLibraryWithFeaturesTest::class) - fun `test AGPInterface#scopeFullLibraryWithFeatures`() = Unit - - @Test - @Case(ProjectTest::class) - fun `test AGPInterface#project`() = Unit - - @Test - @Case(JavaCompilerTaskTestUnit::class) - fun `test AGPInterface#javaCompilerTask`() = Unit - - @Test - @Case(PreBuildTaskTestUnit::class) - fun `test AGPInterface#preBuildTask`() = Unit - - @Test - @Case(AssembleTaskTestUnit::class) - fun `test AGPInterface#assembleTask`() = Unit - - @Test - @Case(MergeAssetsTaskTestUnit::class) - fun `test AGPInterface#mergeAssetsTask`() = Unit - - @Test - @Case(MergeResourcesTaskTestUnit::class) - fun `test AGPInterface#mergeResources`() = Unit - - @Test - @Case(GetTaskNameTestUnit::class) - fun `test AGPInterface#getTaskName(String)`() = Unit - - @Test - @Case(GetTaskName2TestUnit::class) - fun `test AGPInterface#getTaskName(String, String)`() = Unit - - @Test - @Case(VariantDataTestUnit::class) - fun `test AGPInterface#variantData`() = Unit - - @Test - @Case(OriginalApplicationIdTestUnit::class) - fun `test AGPInterface#originalApplicationId`() = Unit - - @Test - @Case(HasDynamicFeatureTestUnit::class) - fun `test AGPInterface#hasDynamicFeature`() = Unit - - @Test - @Case(RawAndroidResourcesTestUnit::class) - fun `test AGPInterface#rawAndroidResources`() = Unit - - @Test - @Case(AllArtifactsTestUnit::class) - fun `test AGPInterface#allArtifacts`() = Unit - - @Test - @Case(MinSdkVersionTestUnit::class) - fun `test AGPInterface#minSdkVersion`() = Unit - - @Test - @Case(TargetSdkVersionTestUnit::class) - fun `test AGPInterface#targetSdkVersion`() = Unit - - @Test - @Case(AarTestUnit::class) - fun `test AGPInterface#aar`() = Unit - - @Test - @Case(ApkTestUnit::class) - fun `test AGPInterface#apk`() = Unit - - @Test - @Case(MergedManifestsTestUnit::class) - fun `test AGPInterface#mergedManifests`() = Unit - - @Test - @Case(MergedResourcesTestUnit::class) - fun `test AGPInterface#mergedRes`() = Unit - - @Test - @Case(MergedAssetsTestUnit::class) - fun `test AGPInterface#mergedAssets`() = Unit - - @Test - @Case(ProcessedResTestUnit::class) - fun `test AGPInterface#processedRes`() = Unit - - @Test - @Case(SymbolListTestUnit::class) - fun `test AGPInterface#symbolList`() = Unit - - @Test - @Case(SymbolListWithPackageNameTestUnit::class) - fun `test AGPInterface#symbolListWithPackageName`() = Unit - - @Test - @Case(AllClassesTestUnit::class) - fun `test AGPInterface#allClasses`() = Unit - - @Test - @Case(BuildToolsTestUnit::class) - fun `test AGPInterface#buildTools`() = Unit - -} - -class V35AppIntegrationTest : V35IntegrationTest(false) - -class V35LibIntegrationTest : V35IntegrationTest(true) - -class ScopeFullWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("PROJECT,SUB_PROJECTS,EXTERNAL_LIBRARIES,FEATURES", AGP.scopeFullWithFeatures.joinToString(",")) - } -} - -class ScopeFullLibraryWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("FEATURES,PROJECT", AGP.scopeFullLibraryWithFeatures.joinToString(",")) - } -} - -class ProjectTest : TestCase { - override fun apply(project: Project) { - val assert: (BaseVariant) -> Unit = { variant -> - assertEquals(project, AGP.run { variant.project }) - } - project.afterEvaluate { - when (val android = project.getAndroid()) { - is AppExtension -> android.applicationVariants.forEach(assert) - is LibraryExtension -> android.libraryVariants.forEach(assert) - } - } - } -} - -class JavaCompilerTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.javaCompilerTask }) - } -} - -class PreBuildTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.preBuildTask }) - } -} - -class AssembleTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.assembleTask }) - } -} - -class MergeAssetsTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeAssetsTask }) - } -} - -class MergeResourcesTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeResourcesTask }) - } -} - -class GetTaskNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("assemble${variant.name.capitalize()}", AGP.run { variant.getTaskName("assemble") }) - } -} - - -class GetTaskName2TestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("merge${variant.name.capitalize()}Resources", AGP.run { variant.getTaskName("merge", "Resources") }) - } -} - -class VariantDataTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.variantData }) - } -} - -class OriginalApplicationIdTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.originalApplicationId }) - } -} - -class HasDynamicFeatureTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertFalse(AGP.run { variant.hasDynamicFeature }) - } -} - -class RawAndroidResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val rawAndroidResources = AGP.run { variant.rawAndroidResources } - assertNotNull(rawAndroidResources) - if (rawAndroidResources.isEmpty) { - fail("rawAndroidResources is empty") - } - rawAndroidResources.forEach { - println(" - ${it.path}") - } - } - } -} - -class AllArtifactsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val allArtifacts = AGP.run { variant.allArtifacts } - assertNotNull(allArtifacts) - if (allArtifacts.isEmpty()) { - fail("allArtifacts is empty") - } - allArtifacts.forEach { (k, v) -> - println(" - $k => $v") - } - } - } -} - -class MinSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val minSdkVersion = AGP.run { variant.minSdkVersion } - assertNotNull(minSdkVersion) - assertEquals(MIN_SDK_VERSION, minSdkVersion.apiLevel) - } -} - -class TargetSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val targetSdkVersion = AGP.run { variant.targetSdkVersion } - assertNotNull(targetSdkVersion) - assertEquals(TARGET_SDK_VERSION, targetSdkVersion.apiLevel) - } -} - -class AarTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.library")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val aar = AGP.run { variant.aar }.search { - it.extension == "aar" - } - if (aar.isEmpty()) { - fail("aar is empty") - } - aar.forEach { - println(" - ${it.path}") - } - } - } -} - -class ApkTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val apk = AGP.run { variant.apk }.search { - it.extension == "apk" - } - if (apk.isEmpty()) { - fail("apk is empty") - } - apk.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedManifestsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedManifests = AGP.run { variant.mergedManifests }.search { - it.name == "AndroidManifest.xml" - } - if (mergedManifests.isEmpty()) { - fail("mergedManifests is empty") - } - mergedManifests.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedResources = AGP.run { variant.mergedRes } - if (mergedResources.isEmpty) { - fail("mergedRes is empty") - } - mergedResources.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedAssetsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doLast { - val mergedAssets = AGP.run { variant.mergedAssets } - println(mergedAssets) - if (mergedAssets.isEmpty) { - fail("mergedAssets is empty") - } - mergedAssets.forEach { - println(" - ${it.path}") - } - } - } -} - -class ProcessedResTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val processedRes = AGP.run { variant.processedRes }.search { - it.extension == "ap_" - } - if (processedRes.isEmpty()) { - fail("processedRes is empty") - } - processedRes.forEach { - println(" - ${it.path}") - } - } - } -} - -class SymbolListTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val symbolList = AGP.run { variant.symbolList } - if (symbolList.isEmpty) { - fail("symbolList is empty") - } - symbolList.forEach { - println(" - ${it.path}") - } - } - } -} - -class SymbolListWithPackageNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val symbolListWithPackageName = AGP.run { variant.symbolListWithPackageName } - if (symbolListWithPackageName.isEmpty) { - fail("symbolListWithPackageName is empty") - } - symbolListWithPackageName.forEach { - println(" - ${it.path}") - } - } - } -} - -class AllClassesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val location = AGP.run { variant.allClasses }.files - assertTrue("ALL_CLASSES: $location", location::isNotEmpty) - assertTrue("No class file found at $location") { - location.search(File::isFile).isNotEmpty() - } - } - } -} - -class BuildToolsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val buildTools = AGP.run { variant.buildTools } - assertNotNull(buildTools) - BuildToolInfo.PathId.values().map { - it.name to buildTools.getPath(it) - }.forEach { (k, v) -> - println(" - $k => $v") - } - } -} diff --git a/booster-android-gradle-v3_5/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_5/V35.kt b/booster-android-gradle-v3_5/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_5/V35.kt deleted file mode 100644 index 23515ab6c..000000000 --- a/booster-android-gradle-v3_5/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_5/V35.kt +++ /dev/null @@ -1,254 +0,0 @@ -package com.didiglobal.booster.android.gradle.v3_5 - -import com.android.build.api.artifact.ArtifactType -import com.android.build.api.artifact.BuildArtifactType -import com.android.build.api.transform.Context -import com.android.build.api.transform.QualifiedContent -import com.android.build.gradle.api.ApplicationVariant -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.LibraryVariant -import com.android.build.gradle.internal.api.artifact.SourceArtifactType -import com.android.build.gradle.internal.pipeline.TransformManager -import com.android.build.gradle.internal.pipeline.TransformTask -import com.android.build.gradle.internal.publishing.AndroidArtifacts -import com.android.build.gradle.internal.scope.AnchorOutputType -import com.android.build.gradle.internal.scope.GlobalScope -import com.android.build.gradle.internal.scope.InternalArtifactType -import com.android.build.gradle.internal.scope.VariantScope -import com.android.build.gradle.internal.scope.getOutputDir -import com.android.build.gradle.internal.variant.BaseVariantData -import com.android.builder.core.DefaultApiVersion -import com.android.builder.core.VariantType -import com.android.builder.model.ApiVersion -import com.android.sdklib.BuildToolInfo -import com.didiglobal.booster.gradle.AGPInterface -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.artifacts.ArtifactCollection -import org.gradle.api.artifacts.component.ComponentIdentifier -import org.gradle.api.artifacts.result.ResolvedArtifactResult -import org.gradle.api.artifacts.result.ResolvedDependencyResult -import org.gradle.api.file.FileCollection -import org.gradle.api.tasks.TaskProvider -import java.io.File -import java.util.TreeMap - -@Suppress("UnstableApiUsage") -private val ARTIFACT_TYPES = arrayOf>( - AnchorOutputType.values(), - BuildArtifactType.values(), - SourceArtifactType.values(), - InternalArtifactType.values() -).flatten().associateBy(ArtifactType::name) - -internal object V35 : AGPInterface { - - @Suppress("UnstableApiUsage") - private fun BaseVariant.getFinalArtifactFiles(type: ArtifactType): FileCollection { - return try { - project.objects.fileCollection().from(variantScope.artifacts.getFinalArtifactFiles(type)) - } catch (e: Throwable) { - project.logger.warn(e.message, e) - project.objects.fileCollection().builtBy(variantScope.artifacts.getFinalArtifactFiles(type)) - } - } - - override val scopeFullWithFeatures: MutableSet - get() = TransformManager.SCOPE_FULL_WITH_FEATURES - - override val scopeFullLibraryWithFeatures: MutableSet - get() = (TransformManager.SCOPE_FEATURES + QualifiedContent.Scope.PROJECT).toMutableSet() - - override val BaseVariant.project: Project - get() = globalScope.project - - override val BaseVariant.javaCompilerTaskProvider: TaskProvider - get() = javaCompileProvider - - override val BaseVariant.preBuildTaskProvider: TaskProvider - get() = preBuildProvider - - override val BaseVariant.assembleTaskProvider: TaskProvider - get() = assembleProvider - - override val BaseVariant.mergeAssetsTaskProvider: TaskProvider - get() = mergeAssetsProvider - - override val BaseVariant.mergeResourcesTaskProvider: TaskProvider - get() = mergeResourcesProvider - - override val BaseVariant.mergeNativeLibsTaskProvider: TaskProvider - get() = project.tasks.named(getTaskName("merge", "NativeLibs")) - - - override val BaseVariant.processJavaResourcesTaskProvider: TaskProvider - get() = processJavaResourcesProvider - - override fun BaseVariant.getTaskName(prefix: String): String { - return variantScope.getTaskName(prefix) - } - - override fun BaseVariant.getTaskName(prefix: String, suffix: String): String { - return variantScope.getTaskName(prefix, suffix) - } - - override val BaseVariant.variantData: BaseVariantData - get() = javaClass.getDeclaredMethod("getVariantData").apply { - isAccessible = true - }.invoke(this) as BaseVariantData - - val BaseVariant.variantScope: VariantScope - get() = variantData.scope - - private val BaseVariant.globalScope: GlobalScope - get() = variantScope.globalScope - - override val BaseVariant.originalApplicationId: String - get() = variantData.variantConfiguration.originalApplicationId - - override val BaseVariant.hasDynamicFeature: Boolean - get() = globalScope.hasDynamicFeatures() - - override val BaseVariant.rawAndroidResources: FileCollection - get() = variantData.allRawAndroidResources - - override val BaseVariant.localAndroidResources: FileCollection - get() = variantData.androidResources.values.map { - it.get() - }.reduce { collection, file -> - collection.plus(file) - } - - override fun BaseVariant.getArtifactCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: AndroidArtifacts.ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): ArtifactCollection { - return variantScope.getArtifactCollection(configType, scope, artifactType) - } - - override fun BaseVariant.getArtifactFileCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: AndroidArtifacts.ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): FileCollection { - return variantScope.getArtifactFileCollection(configType, scope, artifactType) - } - - @Suppress("UnstableApiUsage") - override val BaseVariant.allArtifacts: Map - get() = ARTIFACT_TYPES.entries.associateTo(TreeMap()) { (name, type) -> - val artifacts: FileCollection by lazy { - when (type) { - InternalArtifactType.MERGED_MANIFESTS, - InternalArtifactType.LIBRARY_MANIFEST -> { - project.files(File(type.getOutputDir(globalScope.buildDir), name)) - } - InternalArtifactType.LIBRARY_ASSETS, - InternalArtifactType.MERGED_ASSETS -> { - project.files(File(type.getOutputDir(globalScope.buildDir), "out")) - } - else -> getFinalArtifactFiles(type) - } - } - name to artifacts - } - - override val BaseVariant.minSdkVersion: ApiVersion - get() = DefaultApiVersion(variantData.variantConfiguration.minSdkVersion.apiLevel) - - override val BaseVariant.targetSdkVersion: ApiVersion - get() = variantData.variantConfiguration.targetSdkVersion - - private val BaseVariant.variantType: VariantType - get() = variantScope.type - - override val BaseVariant.isApplication: Boolean - get() = variantType.isApk - - override val BaseVariant.isLibrary: Boolean - get() = variantType.isAar - - override val BaseVariant.isDynamicFeature: Boolean - get() = variantType.isDynamicFeature - - override val BaseVariant.aar: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.AAR) - - override val BaseVariant.apk: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.APK) - - @Suppress("UnstableApiUsage") - override val BaseVariant.mergedManifests: FileCollection - get() = project.files(File(when (this) { - is ApplicationVariant -> InternalArtifactType.MERGED_MANIFESTS - is LibraryVariant -> InternalArtifactType.LIBRARY_MANIFEST - else -> TODO("Unsupported variant type: $variantType") - }.getOutputDir(globalScope.buildDir), name)) - - override val BaseVariant.mergedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.MERGED_RES) - - override val BaseVariant.mergedNativeLibs: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.MERGED_NATIVE_LIBS) - - @Suppress("UnstableApiUsage") - override val BaseVariant.mergedAssets: FileCollection - get() = project.files(File(when (this) { - is ApplicationVariant -> InternalArtifactType.MERGED_ASSETS - is LibraryVariant -> InternalArtifactType.LIBRARY_ASSETS - else -> TODO("Unsupported variant type: $variantType") - }.getOutputDir(globalScope.buildDir), "out")) - - override val BaseVariant.processedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.PROCESSED_RES) - - override val BaseVariant.symbolList: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.SYMBOL_LIST) - - override val BaseVariant.symbolListWithPackageName: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.SYMBOL_LIST_WITH_PACKAGE_NAME) - - override val BaseVariant.dataBindingDependencyArtifacts: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.DATA_BINDING_DEPENDENCY_ARTIFACTS) - - override val BaseVariant.allClasses: FileCollection - get() = getFinalArtifactFiles(AnchorOutputType.ALL_CLASSES) - - override val BaseVariant.buildTools: BuildToolInfo - get() = globalScope.sdkComponents.buildToolInfoProvider.get() - - override val BaseVariant.isPrecompileDependenciesResourcesEnabled: Boolean - get() = false - - override fun BaseVariant.getDependencies(transitive: Boolean, filter: (ComponentIdentifier) -> Boolean): Collection { - val all = listOf(AndroidArtifacts.ArtifactType.AAR, AndroidArtifacts.ArtifactType.JAR) - .asSequence() - .map { - getArtifactCollection(AndroidArtifacts.ConsumedConfigType.RUNTIME_CLASSPATH, AndroidArtifacts.ArtifactScope.ALL, it).filter { result -> - filter(result.id.componentIdentifier) - } - } - .flatten() - .associateBy { - it.id.componentIdentifier.displayName - } - val result = if (!transitive) { - runtimeConfiguration.incoming.resolutionResult.root.dependencies.filterIsInstance().mapNotNull { - it.selected.id.displayName.takeIf { id -> id in all.keys } - }.associateWith { - all[it]!! - } - } else { - all - } - return result.values.toSet() - } - - override val Context.task: TransformTask - get() = this as TransformTask - - override val Project.aapt2Enabled: Boolean - get() = true - -} diff --git a/booster-android-gradle-v3_6/README.md b/booster-android-gradle-v3_6/README.md deleted file mode 100644 index 0858da90e..000000000 --- a/booster-android-gradle-v3_6/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# booster-android-gradle-v3_6 - -This module is an implementation of [booster-android-gradle-api](../booster-android-gradle-api) for Android gradle plugin above 3.6. - -本模块是 [booster-android-gradle-api](../booster-android-gradle-api) 针对 Android gradle plugin 3.6 以上版本的实现。 - diff --git a/booster-android-gradle-v3_6/build.gradle b/booster-android-gradle-v3_6/build.gradle deleted file mode 100644 index fea47241c..000000000 --- a/booster-android-gradle-v3_6/build.gradle +++ /dev/null @@ -1,19 +0,0 @@ -apply plugin: 'java-gradle-plugin' - -apply from: "$rootDir/gradle/booster.gradle" -apply from: "$rootDir/gradle/integration-test.gradle" -apply from: "$rootDir/gradle/functional-test.gradle" - -dependencies { - kapt 'com.google.auto.service:auto-service:1.0' - api 'com.google.auto.service:auto-service:1.0' - api project(':booster-android-gradle-compat') - compileOnly 'com.android.tools.build:gradle:3.6.0' - testImplementation 'com.android.tools.build:gradle:3.6.0' - testImplementation 'io.bootstage.testkit:testkit-gradle-plugin:1.4.0' - testImplementation project(':booster-build') -} - -gradlePlugin { - testSourceSets sourceSets.functionalTest, sourceSets.integrationTest -} diff --git a/booster-android-gradle-v3_6/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v3_6/V36IntegrationTest.kt b/booster-android-gradle-v3_6/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v3_6/V36IntegrationTest.kt deleted file mode 100644 index 135cb3b14..000000000 --- a/booster-android-gradle-v3_6/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v3_6/V36IntegrationTest.kt +++ /dev/null @@ -1,479 +0,0 @@ -@file:Suppress("DEPRECATION") - -package com.didiglobal.booster.android.gradle.v3_6 - -import com.android.build.gradle.AppExtension -import com.android.build.gradle.BaseExtension -import com.android.build.gradle.LibraryExtension -import com.android.build.gradle.api.BaseVariant -import com.android.sdklib.BuildToolInfo -import com.didiglobal.booster.gradle.AGP -import com.didiglobal.booster.gradle.getAndroid -import com.didiglobal.booster.kotlinx.search -import io.bootstage.testkit.gradle.Case -import io.bootstage.testkit.gradle.TestCase -import io.bootstage.testkit.gradle.VariantTestCase -import io.bootstage.testkit.gradle.rules.GradleExecutor -import io.bootstage.testkit.gradle.rules.LocalProperties -import io.bootstage.testkit.gradle.rules.copyFromResource -import io.bootstage.testkit.gradle.rules.rule -import org.gradle.api.Project -import org.junit.Before -import org.junit.Rule -import org.junit.rules.TemporaryFolder -import org.junit.rules.TestRule -import java.io.File -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertNotNull -import kotlin.test.assertTrue -import kotlin.test.fail - -private val MIN_SDK_VERSION = System.getProperty("android.minsdk.version").toInt() - -private const val TARGET_SDK_VERSION = 26 - -private val ARGS = System.getProperty("gradle.args").split("\\s+".toRegex()) + listOf( - "-Pbooster_version=${Build.VERSION}", - "-Pandroid_gradle_version=3.6.0", - "-Pcompile_sdk_version=28", - "-Pbuild_tools_version=26.0.3", - "-Pmin_sdk_version=${MIN_SDK_VERSION}", - "-Ptarget_sdk_version=${TARGET_SDK_VERSION}" -) - -@Suppress("RemoveCurlyBracesFromTemplate", "FunctionName") -abstract class V36IntegrationTest(private val isLib: Boolean) { - - private val projectDir = TemporaryFolder() - - @get:Rule - val ruleChain: TestRule = rule(projectDir) { - rule(LocalProperties(projectDir::getRoot)) { - GradleExecutor(projectDir::getRoot, "5.6.4", *ARGS.toTypedArray()) - } - } - - @Before - fun setup() { - projectDir.copyFromResource("${if (isLib) "lib" else "app"}.gradle", "build.gradle") - projectDir.copyFromResource("buildSrc") - projectDir.copyFromResource("src") - projectDir.newFile("gradle.properties").writeText("org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=2g") - assertEquals(3, AGP.revision.major) - assertEquals(6, AGP.revision.minor) - } - - @Test - @Case(ScopeFullWithFeaturesTest::class) - fun `test AGPInterface#scopeFullWithFeatures`() = Unit - - @Test - @Case(ScopeFullLibraryWithFeaturesTest::class) - fun `test AGPInterface#scopeFullLibraryWithFeatures`() = Unit - - @Test - @Case(ProjectTest::class) - fun `test AGPInterface#project`() = Unit - - @Test - @Case(JavaCompilerTaskTestUnit::class) - fun `test AGPInterface#javaCompilerTask`() = Unit - - @Test - @Case(PreBuildTaskTestUnit::class) - fun `test AGPInterface#preBuildTask`() = Unit - - @Test - @Case(AssembleTaskTestUnit::class) - fun `test AGPInterface#assembleTask`() = Unit - - @Test - @Case(MergeAssetsTaskTestUnit::class) - fun `test AGPInterface#mergeAssetsTask`() = Unit - - @Test - @Case(MergeResourcesTaskTestUnit::class) - fun `test AGPInterface#mergeResources`() = Unit - - @Test - @Case(GetTaskNameTestUnit::class) - fun `test AGPInterface#getTaskName(String)`() = Unit - - @Test - @Case(GetTaskName2TestUnit::class) - fun `test AGPInterface#getTaskName(String, String)`() = Unit - - @Test - @Case(VariantDataTestUnit::class) - fun `test AGPInterface#variantData`() = Unit - - @Test - @Case(OriginalApplicationIdTestUnit::class) - fun `test AGPInterface#originalApplicationId`() = Unit - - @Test - @Case(HasDynamicFeatureTestUnit::class) - fun `test AGPInterface#hasDynamicFeature`() = Unit - - @Test - @Case(RawAndroidResourcesTestUnit::class) - fun `test AGPInterface#rawAndroidResources`() = Unit - - @Test - @Case(AllArtifactsTestUnit::class) - fun `test AGPInterface#allArtifacts`() = Unit - - @Test - @Case(MinSdkVersionTestUnit::class) - fun `test AGPInterface#minSdkVersion`() = Unit - - @Test - @Case(TargetSdkVersionTestUnit::class) - fun `test AGPInterface#targetSdkVersion`() = Unit - - @Test - @Case(AarTestUnit::class) - fun `test AGPInterface#aar`() = Unit - - @Test - @Case(ApkTestUnit::class) - fun `test AGPInterface#apk`() = Unit - - @Test - @Case(MergedManifestsTestUnit::class) - fun `test AGPInterface#mergedManifests`() = Unit - - @Test - @Case(MergedResourcesTestUnit::class) - fun `test AGPInterface#mergedRes`() = Unit - - @Test - @Case(MergedAssetsTestUnit::class) - fun `test AGPInterface#mergedAssets`() = Unit - - @Test - @Case(ProcessedResTestUnit::class) - fun `test AGPInterface#processedRes`() = Unit - - @Test - @Case(SymbolListTestUnit::class) - fun `test AGPInterface#symbolList`() = Unit - - @Test - @Case(SymbolListWithPackageNameTestUnit::class) - fun `test AGPInterface#symbolListWithPackageName`() = Unit - - @Test - @Case(AllClassesTestUnit::class) - fun `test AGPInterface#allClasses`() = Unit - - @Test - @Case(BuildToolsTestUnit::class) - fun `test AGPInterface#buildTools`() = Unit - -} - -class V36AppIntegrationTest : V36IntegrationTest(false) - -class V36LibIntegrationTest : V36IntegrationTest(true) - -class ScopeFullWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("PROJECT,SUB_PROJECTS,EXTERNAL_LIBRARIES,FEATURES", AGP.scopeFullWithFeatures.joinToString(",")) - } -} - -class ScopeFullLibraryWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("FEATURES,PROJECT", AGP.scopeFullLibraryWithFeatures.joinToString(",")) - } -} - -class ProjectTest : TestCase { - override fun apply(project: Project) { - val assert: (BaseVariant) -> Unit = { variant -> - assertEquals(project, AGP.run { variant.project }) - } - project.afterEvaluate { - when (val android = project.getAndroid()) { - is AppExtension -> android.applicationVariants.forEach(assert) - is LibraryExtension -> android.libraryVariants.forEach(assert) - } - } - } -} - -class JavaCompilerTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.javaCompilerTask }) - } -} - -class PreBuildTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.preBuildTask }) - } -} - -class AssembleTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.assembleTask }) - } -} - -class MergeAssetsTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeAssetsTask }) - } -} - -class MergeResourcesTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeResourcesTask }) - } -} - -class GetTaskNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("assemble${variant.name.capitalize()}", AGP.run { variant.getTaskName("assemble") }) - } -} - - -class GetTaskName2TestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("merge${variant.name.capitalize()}Resources", AGP.run { variant.getTaskName("merge", "Resources") }) - } -} - -class VariantDataTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.variantData }) - } -} - -class OriginalApplicationIdTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.originalApplicationId }) - } -} - -class HasDynamicFeatureTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertFalse(AGP.run { variant.hasDynamicFeature }) - } -} - -class RawAndroidResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val rawAndroidResources = AGP.run { variant.rawAndroidResources } - assertNotNull(rawAndroidResources) - if (rawAndroidResources.isEmpty) { - fail("rawAndroidResources is empty") - } - rawAndroidResources.forEach { - println(" - ${it.path}") - } - } - } -} - -class AllArtifactsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val allArtifacts = AGP.run { variant.allArtifacts } - assertNotNull(allArtifacts) - if (allArtifacts.isEmpty()) { - fail("allArtifacts is empty") - } - allArtifacts.forEach { (k, v) -> - println(" - $k => $v") - } - } - } -} - -class MinSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val minSdkVersion = AGP.run { variant.minSdkVersion } - assertNotNull(minSdkVersion) - assertEquals(MIN_SDK_VERSION, minSdkVersion.apiLevel) - } -} - -class TargetSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val targetSdkVersion = AGP.run { variant.targetSdkVersion } - assertNotNull(targetSdkVersion) - assertEquals(TARGET_SDK_VERSION, targetSdkVersion.apiLevel) - } -} - -class AarTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.library")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val location = AGP.run { variant.aar }.files - assertTrue("AAR: $location", location::isNotEmpty) - assertTrue("No aar found at $location") { - location.search { - it.extension == "aar" - }.isNotEmpty() - } - } - } -} - -class ApkTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val apk = AGP.run { variant.apk }.search { - it.extension == "apk" - } - if (apk.isEmpty()) { - fail("apk is empty") - } - apk.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedManifestsTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedManifests = AGP.run { variant.mergedManifests }.search { - it.name == "AndroidManifest.xml" - } - if (mergedManifests.isEmpty()) { - fail("mergedManifests is empty") - } - mergedManifests.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedResources = AGP.run { variant.mergedRes } - if (mergedResources.isEmpty) { - fail("mergedRes is empty") - } - mergedResources.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedAssetsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedAssets = AGP.run { variant.mergedAssets } - if (mergedAssets.isEmpty) { - fail("mergedAssets is empty") - } - mergedAssets.forEach { - println(" - ${it.path}") - } - } - } -} - -class ProcessedResTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val processedRes = AGP.run { variant.processedRes }.search { - it.extension == "ap_" - } - if (processedRes.isEmpty()) { - fail("processedRes is empty") - } - processedRes.forEach { - println(" - ${it.path}") - } - } - } -} - -class SymbolListTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val symbolList = AGP.run { variant.symbolList } - if (symbolList.isEmpty) { - fail("symbolList is empty") - } - symbolList.forEach { - println(" - ${it.path}") - } - } - } -} - -class SymbolListWithPackageNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val symbolListWithPackageName = AGP.run { variant.symbolListWithPackageName } - if (symbolListWithPackageName.isEmpty) { - fail("symbolListWithPackageName is empty") - } - symbolListWithPackageName.forEach { - println(" - ${it.path}") - } - } - } -} - -class AllClassesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val location = AGP.run { variant.allClasses }.files - assertTrue("ALL_CLASSES: $location", location::isNotEmpty) - assertTrue("No class file found at $location") { - location.search(File::isFile).isNotEmpty() - } - } - } -} - -class BuildToolsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val buildTools = AGP.run { variant.buildTools } - assertNotNull(buildTools) - BuildToolInfo.PathId.values().map { - it.name to buildTools.getPath(it) - }.forEach { (k, v) -> - println(" - $k => $v") - } - } -} diff --git a/booster-android-gradle-v3_6/src/integrationTest/resources/lib.gradle b/booster-android-gradle-v3_6/src/integrationTest/resources/lib.gradle deleted file mode 100644 index adc9b1ca0..000000000 --- a/booster-android-gradle-v3_6/src/integrationTest/resources/lib.gradle +++ /dev/null @@ -1,57 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } - dependencies { - classpath "com.android.tools.build:gradle:${project.android_gradle_version}" - classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { - exclude group: 'com.google.guava' - } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" - } -} - -apply plugin: 'com.android.library' -apply plugin: 'com.didiglobal.booster' -apply plugin: 'io.bootstage.testkit' - -android { - compileSdkVersion project.compile_sdk_version as Integer - buildToolsVersion project.build_tools_version - defaultConfig { - minSdkVersion project.min_sdk_version as Integer - targetSdkVersion project.target_sdk_version as Integer - versionCode 1 - versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - buildTypes { - debug { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - flavorDimensions 'lang' - productFlavors { - en { - dimension 'lang' - } - cn { - dimension 'lang' - } - } - lintOptions { - checkReleaseBuilds false - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} diff --git a/booster-android-gradle-v3_6/src/integrationTest/resources/src/main/AndroidManifest.xml b/booster-android-gradle-v3_6/src/integrationTest/resources/src/main/AndroidManifest.xml deleted file mode 100644 index 30800c604..000000000 --- a/booster-android-gradle-v3_6/src/integrationTest/resources/src/main/AndroidManifest.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/booster-android-gradle-v3_6/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java b/booster-android-gradle-v3_6/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java deleted file mode 100644 index 0eb4ec7b4..000000000 --- a/booster-android-gradle-v3_6/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.didiglobal.booster.android.test; - -import android.app.Activity; - -public class MainActivity extends Activity { -} \ No newline at end of file diff --git a/booster-android-gradle-v3_6/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java b/booster-android-gradle-v3_6/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java deleted file mode 100644 index 3ecfb1507..000000000 --- a/booster-android-gradle-v3_6/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.didiglobal.booster.android.test; - -import android.app.Application; - -public class TestApplication extends Application { - -} \ No newline at end of file diff --git a/booster-android-gradle-v3_6/src/integrationTest/resources/src/main/res/values/strings.xml b/booster-android-gradle-v3_6/src/integrationTest/resources/src/main/res/values/strings.xml deleted file mode 100644 index 8b2247616..000000000 --- a/booster-android-gradle-v3_6/src/integrationTest/resources/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - Test - \ No newline at end of file diff --git a/booster-android-gradle-v3_6/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_6/V36.kt b/booster-android-gradle-v3_6/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_6/V36.kt deleted file mode 100644 index bb9188445..000000000 --- a/booster-android-gradle-v3_6/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_6/V36.kt +++ /dev/null @@ -1,264 +0,0 @@ -package com.didiglobal.booster.android.gradle.v3_6 - -import com.android.build.api.artifact.ArtifactType -import com.android.build.api.artifact.BuildArtifactType -import com.android.build.api.transform.Context -import com.android.build.api.transform.QualifiedContent -import com.android.build.gradle.AppPlugin -import com.android.build.gradle.DynamicFeaturePlugin -import com.android.build.gradle.LibraryPlugin -import com.android.build.gradle.api.ApplicationVariant -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.LibraryVariant -import com.android.build.gradle.internal.api.artifact.SourceArtifactType -import com.android.build.gradle.internal.pipeline.TransformManager -import com.android.build.gradle.internal.pipeline.TransformTask -import com.android.build.gradle.internal.publishing.AndroidArtifacts -import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactScope -import com.android.build.gradle.internal.scope.AnchorOutputType -import com.android.build.gradle.internal.scope.GlobalScope -import com.android.build.gradle.internal.scope.InternalArtifactType -import com.android.build.gradle.internal.scope.VariantScope -import com.android.build.gradle.internal.variant.BaseVariantData -import com.android.builder.core.DefaultApiVersion -import com.android.builder.core.VariantType -import com.android.builder.model.ApiVersion -import com.android.sdklib.BuildToolInfo -import com.didiglobal.booster.gradle.AGPInterface -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.artifacts.ArtifactCollection -import org.gradle.api.artifacts.component.ComponentIdentifier -import org.gradle.api.artifacts.result.ResolvedArtifactResult -import org.gradle.api.artifacts.result.ResolvedDependencyResult -import org.gradle.api.file.FileCollection -import org.gradle.api.file.FileSystemLocation -import org.gradle.api.tasks.TaskProvider -import java.io.File -import java.util.TreeMap - -@Suppress("UnstableApiUsage") -internal val ARTIFACT_TYPES = arrayOf( - AnchorOutputType::class, - BuildArtifactType::class, - SourceArtifactType::class, - InternalArtifactType::class -).map { - it.sealedSubclasses -}.flatten().map { - it.objectInstance as ArtifactType -}.associateBy { - it.javaClass.simpleName -} - -object V36 : AGPInterface { - - @Suppress("UnstableApiUsage") - private fun BaseVariant.getFinalArtifactFiles(type: ArtifactType): FileCollection { - return try { - project.objects.fileCollection().from(variantScope.artifacts.getFinalProducts(type)) - } catch (e: Throwable) { - project.objects.fileCollection().builtBy(variantScope.artifacts.getFinalProducts(type)) - } - } - - override val scopeFullWithFeatures: MutableSet - get() = TransformManager.SCOPE_FULL_WITH_FEATURES - - override val scopeFullLibraryWithFeatures: MutableSet - get() = (TransformManager.SCOPE_FEATURES + QualifiedContent.Scope.PROJECT).toMutableSet() - - override val BaseVariant.project: Project - get() = globalScope.project - - override val BaseVariant.javaCompilerTaskProvider: TaskProvider - get() = javaCompileProvider - - override val BaseVariant.preBuildTaskProvider: TaskProvider - get() = preBuildProvider - - override val BaseVariant.assembleTaskProvider: TaskProvider - get() = assembleProvider - - override val BaseVariant.mergeAssetsTaskProvider: TaskProvider - get() = mergeAssetsProvider - - override val BaseVariant.mergeResourcesTaskProvider: TaskProvider - get() = try { - project.tasks.named(getTaskName("merge", "Resources")) - } catch (e: Throwable) { - mergeResourcesProvider - } - - override val BaseVariant.mergeNativeLibsTaskProvider: TaskProvider - get() = project.tasks.named(getTaskName("merge", "NativeLibs")) - - override val BaseVariant.processJavaResourcesTaskProvider: TaskProvider - get() = processJavaResourcesProvider - - override fun BaseVariant.getTaskName(prefix: String): String { - return variantScope.getTaskName(prefix) - } - - override fun BaseVariant.getTaskName(prefix: String, suffix: String): String { - return variantScope.getTaskName(prefix, suffix) - } - - override val BaseVariant.variantData: BaseVariantData - get() = javaClass.getDeclaredMethod("getVariantData").apply { - isAccessible = true - }.invoke(this) as BaseVariantData - - val BaseVariant.variantScope: VariantScope - get() = variantData.scope - - private val BaseVariant.globalScope: GlobalScope - get() = variantScope.globalScope - - override val BaseVariant.originalApplicationId: String - get() = variantData.variantConfiguration.originalApplicationId - - override val BaseVariant.hasDynamicFeature: Boolean - get() = globalScope.hasDynamicFeatures() - - override val BaseVariant.rawAndroidResources: FileCollection - get() = variantData.allRawAndroidResources - - override val BaseVariant.localAndroidResources: FileCollection - get() = variantData.androidResources.values.reduce { collection, file -> - collection.plus(file) - } - - override fun BaseVariant.getArtifactCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): ArtifactCollection { - return variantScope.getArtifactCollection(configType, scope, artifactType) - } - - override fun BaseVariant.getArtifactFileCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): FileCollection { - return variantScope.getArtifactFileCollection(configType, scope, artifactType) - } - - override val BaseVariant.allArtifacts: Map - get() = ARTIFACT_TYPES.entries.associateTo(TreeMap()) { (name, type) -> - val artifacts: FileCollection by lazy { - getFinalArtifactFiles(type) - } - name to artifacts - } - - override val BaseVariant.minSdkVersion: ApiVersion - get() = DefaultApiVersion(variantData.variantConfiguration.minSdkVersion.apiLevel) - - override val BaseVariant.targetSdkVersion: ApiVersion - get() = variantData.variantConfiguration.targetSdkVersion - - private val BaseVariant.variantType: VariantType - get() = variantScope.type - - override val BaseVariant.isApplication: Boolean - get() = project.plugins.hasPlugin(AppPlugin::class.java) - override val BaseVariant.isLibrary: Boolean - get() = project.plugins.hasPlugin(LibraryPlugin::class.java) - override val BaseVariant.isDynamicFeature: Boolean - get() = project.plugins.hasPlugin(DynamicFeaturePlugin::class.java) - - override val BaseVariant.aar: FileCollection - get() = project.files(variantScope.aarLocation.absolutePath) - - override val BaseVariant.apk: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.APK) - - override val BaseVariant.mergedManifests: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.MERGED_MANIFESTS) - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.LIBRARY_MANIFEST) - else -> TODO("Unsupported variant type: $variantType") - } - - override val BaseVariant.mergedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.MERGED_RES) - - override val BaseVariant.mergedNativeLibs: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.MERGED_NATIVE_LIBS) - - @Suppress("UnstableApiUsage") - override val BaseVariant.mergedAssets: FileCollection - get() = getFinalArtifactFiles(when (this) { - is ApplicationVariant -> InternalArtifactType.MERGED_ASSETS - is LibraryVariant -> InternalArtifactType.LIBRARY_ASSETS - else -> TODO("Unsupported variant type: $variantType") - }) - - override val BaseVariant.processedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.PROCESSED_RES) - - override val BaseVariant.symbolList: FileCollection - get() = getFinalArtifactFiles(when (this) { - is ApplicationVariant -> InternalArtifactType.RUNTIME_SYMBOL_LIST - is LibraryVariant -> InternalArtifactType.COMPILE_SYMBOL_LIST - else -> TODO("Unsupported variant type : $variantType") - }) - - override val BaseVariant.symbolListWithPackageName: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.SYMBOL_LIST_WITH_PACKAGE_NAME) - - override val BaseVariant.dataBindingDependencyArtifacts: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.DATA_BINDING_DEPENDENCY_ARTIFACTS) - - override val BaseVariant.allClasses: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.JAVAC) + project.files("build${File.separator}tmp${File.separator}kotlin-classes${File.separator}${dirName}") - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.AAR_MAIN_JAR) - else -> project.files() - } - - override val BaseVariant.buildTools: BuildToolInfo - get() = globalScope.sdkComponents.buildToolInfoProvider.get() - - override val BaseVariant.isPrecompileDependenciesResourcesEnabled: Boolean - get() = variantScope.isPrecompileDependenciesResourcesEnabled - - override fun BaseVariant.getDependencies(transitive: Boolean, filter: (ComponentIdentifier) -> Boolean): Collection { - val all = listOf(AndroidArtifacts.ArtifactType.AAR, AndroidArtifacts.ArtifactType.JAR) - .asSequence() - .map { - getArtifactCollection(AndroidArtifacts.ConsumedConfigType.RUNTIME_CLASSPATH, ArtifactScope.ALL, it).filter { result -> - filter(result.id.componentIdentifier) - } - } - .flatten() - .associateBy { - it.id.componentIdentifier.displayName - } - val result = if (!transitive) { - runtimeConfiguration.incoming.resolutionResult.root.dependencies.filterIsInstance().mapNotNull { - it.selected.id.displayName.takeIf { id -> id in all.keys } - }.associateWith { - all[it]!! - } - } else { - all - } - return result.values.toSet() - } - - override val Context.task: TransformTask - get() = javaClass.getDeclaredField("this$1").apply { - isAccessible = true - }.get(this).run { - javaClass.getDeclaredField("this$0").apply { - isAccessible = true - }.get(this) - } as TransformTask - - override val Project.aapt2Enabled: Boolean - get() = true - -} diff --git a/booster-android-gradle-v3_6/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_6/V36Factory.kt b/booster-android-gradle-v3_6/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_6/V36Factory.kt deleted file mode 100644 index 1d65da31f..000000000 --- a/booster-android-gradle-v3_6/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_6/V36Factory.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.didiglobal.booster.android.gradle.v3_6 - -import com.android.repository.Revision -import com.didiglobal.booster.gradle.AGPInterface -import com.didiglobal.booster.gradle.AGPInterfaceFactory -import com.google.auto.service.AutoService - -@AutoService(AGPInterfaceFactory::class) -class V36Factory : AGPInterfaceFactory { - - override val revision: Revision = Revision(3, 6, 0) - - override fun newAGPInterface(): AGPInterface = V36 - -} diff --git a/booster-android-gradle-v4_0/README.md b/booster-android-gradle-v4_0/README.md deleted file mode 100644 index a69564199..000000000 --- a/booster-android-gradle-v4_0/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# booster-android-gradle-v4_0 - -This module is an implementation of [booster-android-gradle-api](../booster-android-gradle-api) for Android gradle plugin above 4.0. - -本模块是 [booster-android-gradle-api](../booster-android-gradle-api) 针对 Android gradle plugin 4.0 以上版本的实现。 - diff --git a/booster-android-gradle-v4_0/build.gradle b/booster-android-gradle-v4_0/build.gradle deleted file mode 100644 index 94b0d1476..000000000 --- a/booster-android-gradle-v4_0/build.gradle +++ /dev/null @@ -1,19 +0,0 @@ -apply plugin: 'java-gradle-plugin' - -apply from: "$rootDir/gradle/booster.gradle" -apply from: "$rootDir/gradle/integration-test.gradle" -apply from: "$rootDir/gradle/functional-test.gradle" - -dependencies { - kapt 'com.google.auto.service:auto-service:1.0' - api 'com.google.auto.service:auto-service:1.0' - api project(':booster-android-gradle-compat') - compileOnly 'com.android.tools.build:gradle:4.0.0' - testImplementation 'com.android.tools.build:gradle:4.0.0' - testImplementation 'io.bootstage.testkit:testkit-gradle-plugin:1.4.0' - testImplementation project(':booster-build') -} - -gradlePlugin { - testSourceSets sourceSets.functionalTest, sourceSets.integrationTest -} \ No newline at end of file diff --git a/booster-android-gradle-v4_0/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v4_0/V40IntegrationTest.kt b/booster-android-gradle-v4_0/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v4_0/V40IntegrationTest.kt deleted file mode 100644 index be401bfde..000000000 --- a/booster-android-gradle-v4_0/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v4_0/V40IntegrationTest.kt +++ /dev/null @@ -1,481 +0,0 @@ -@file:Suppress("DEPRECATION") - -package com.didiglobal.booster.android.gradle.v4_0 - -import com.android.build.gradle.AppExtension -import com.android.build.gradle.BaseExtension -import com.android.build.gradle.LibraryExtension -import com.android.build.gradle.api.BaseVariant -import com.android.sdklib.BuildToolInfo -import com.didiglobal.booster.gradle.AGP -import com.didiglobal.booster.gradle.getAndroid -import com.didiglobal.booster.kotlinx.search -import io.bootstage.testkit.gradle.Case -import io.bootstage.testkit.gradle.TestCase -import io.bootstage.testkit.gradle.VariantTestCase -import io.bootstage.testkit.gradle.rules.GradleExecutor -import io.bootstage.testkit.gradle.rules.LocalProperties -import io.bootstage.testkit.gradle.rules.copyFromResource -import io.bootstage.testkit.gradle.rules.rule -import org.gradle.api.Project -import org.junit.Before -import org.junit.Rule -import org.junit.rules.TemporaryFolder -import org.junit.rules.TestRule -import java.io.File -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertNotNull -import kotlin.test.assertTrue -import kotlin.test.fail - -private val MIN_SDK_VERSION = System.getProperty("android.minsdk.version").toInt() - -private const val TARGET_SDK_VERSION = 26 - -private val ARGS = System.getProperty("gradle.args").split("\\s+".toRegex()) + listOf( - "-Pbooster_version=${Build.VERSION}", - "-Pandroid_gradle_version=4.0.0", - "-Pcompile_sdk_version=28", - "-Pbuild_tools_version=26.0.3", - "-Pmin_sdk_version=${MIN_SDK_VERSION}", - "-Ptarget_sdk_version=${TARGET_SDK_VERSION}" -) - -@Suppress("RemoveCurlyBracesFromTemplate", "FunctionName") -abstract class V40IntegrationTest(private val isLib: Boolean) { - - private val projectDir = TemporaryFolder() - - @get:Rule - val ruleChain: TestRule = rule(projectDir) { - rule(LocalProperties(projectDir::getRoot)) { - GradleExecutor(projectDir::getRoot, "6.1.1", *ARGS.toTypedArray()) - } - } - - @Before - fun setup() { - projectDir.copyFromResource("${if (isLib) "lib" else "app"}.gradle", "build.gradle") - projectDir.copyFromResource("buildSrc") - projectDir.copyFromResource("src") - projectDir.newFile("gradle.properties").writeText("org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=2g") - assertEquals(4, AGP.revision.major) - assertEquals(0, AGP.revision.minor) - } - - @Test - @Case(ScopeFullWithFeaturesTest::class) - fun `test AGPInterface#scopeFullWithFeatures`() = Unit - - @Test - @Case(ScopeFullLibraryWithFeaturesTest::class) - fun `test AGPInterface#scopeFullLibraryWithFeatures`() = Unit - - @Test - @Case(ProjectTest::class) - fun `test AGPInterface#project`() = Unit - - @Test - @Case(JavaCompilerTaskTestUnit::class) - fun `test AGPInterface#javaCompilerTask`() = Unit - - @Test - @Case(PreBuildTaskTestUnit::class) - fun `test AGPInterface#preBuildTask`() = Unit - - @Test - @Case(AssembleTaskTestUnit::class) - fun `test AGPInterface#assembleTask`() = Unit - - @Test - @Case(MergeAssetsTaskTestUnit::class) - fun `test AGPInterface#mergeAssetsTask`() = Unit - - @Test - @Case(MergeResourcesTaskTestUnit::class) - fun `test AGPInterface#mergeResources`() = Unit - - @Test - @Case(GetTaskNameTestUnit::class) - fun `test AGPInterface#getTaskName(String)`() = Unit - - @Test - @Case(GetTaskName2TestUnit::class) - fun `test AGPInterface#getTaskName(String, String)`() = Unit - - @Test - @Case(VariantDataTestUnit::class) - fun `test AGPInterface#variantData`() = Unit - - @Test - @Case(OriginalApplicationIdTestUnit::class) - fun `test AGPInterface#originalApplicationId`() = Unit - - @Test - @Case(HasDynamicFeatureTestUnit::class) - fun `test AGPInterface#hasDynamicFeature`() = Unit - - @Test - @Case(RawAndroidResourcesTestUnit::class) - fun `test AGPInterface#rawAndroidResources`() = Unit - - @Test - @Case(AllArtifactsTestUnit::class) - fun `test AGPInterface#allArtifacts`() = Unit - - @Test - @Case(MinSdkVersionTestUnit::class) - fun `test AGPInterface#minSdkVersion`() = Unit - - @Test - @Case(TargetSdkVersionTestUnit::class) - fun `test AGPInterface#targetSdkVersion`() = Unit - - @Test - @Case(AarTestUnit::class) - fun `test AGPInterface#aar`() = Unit - - @Test - @Case(ApkTestUnit::class) - fun `test AGPInterface#apk`() = Unit - - @Test - @Case(MergedManifestsTestUnit::class) - fun `test AGPInterface#mergedManifests`() = Unit - - @Test - @Case(MergedResourcesTestUnit::class) - fun `test AGPInterface#mergedRes`() = Unit - - @Test - @Case(MergedAssetsTestUnit::class) - fun `test AGPInterface#mergedAssets`() = Unit - - @Test - @Case(ProcessedResTestUnit::class) - fun `test AGPInterface#processedRes`() = Unit - - @Test - @Case(SymbolListTestUnit::class) - fun `test AGPInterface#symbolList`() = Unit - - @Test - @Case(SymbolListWithPackageNameTestUnit::class) - fun `test AGPInterface#symbolListWithPackageName`() = Unit - - @Test - @Case(AllClassesTestUnit::class) - fun `test AGPInterface#allClasses`() = Unit - - @Test - @Case(BuildToolsTestUnit::class) - fun `test AGPInterface#buildTools`() = Unit - -} - -class V40AppIntegrationTest : V40IntegrationTest(false) - -class V40LibIntegrationTest : V40IntegrationTest(true) - -class ScopeFullWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("PROJECT,SUB_PROJECTS,EXTERNAL_LIBRARIES,FEATURES", AGP.scopeFullWithFeatures.joinToString(",")) - } -} - -class ScopeFullLibraryWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("FEATURES,PROJECT", AGP.scopeFullLibraryWithFeatures.joinToString(",")) - } -} - -class ProjectTest : TestCase { - override fun apply(project: Project) { - val assert: (BaseVariant) -> Unit = { variant -> - assertEquals(project, AGP.run { variant.project }) - } - project.afterEvaluate { - when (val android = project.getAndroid()) { - is AppExtension -> android.applicationVariants.forEach(assert) - is LibraryExtension -> android.libraryVariants.forEach(assert) - } - } - } -} - -class JavaCompilerTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.javaCompilerTask }) - } -} - -class PreBuildTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.preBuildTask }) - } -} - -class AssembleTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.assembleTask }) - } -} - -class MergeAssetsTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeAssetsTask }) - } -} - -class MergeResourcesTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeResourcesTask }) - } -} - -class GetTaskNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("assemble${variant.name.capitalize()}", AGP.run { variant.getTaskName("assemble") }) - } -} - - -class GetTaskName2TestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("merge${variant.name.capitalize()}Resources", AGP.run { variant.getTaskName("merge", "Resources") }) - } -} - -class VariantDataTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.variantData }) - } -} - -class OriginalApplicationIdTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.originalApplicationId }) - } -} - -class HasDynamicFeatureTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertFalse(AGP.run { variant.hasDynamicFeature }) - } -} - -class RawAndroidResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val rawAndroidResources = AGP.run { variant.rawAndroidResources } - assertNotNull(rawAndroidResources) - if (rawAndroidResources.isEmpty) { - fail("rawAndroidResources is empty") - } - rawAndroidResources.forEach { - println(" - ${it.path}") - } - } - } -} - -class AllArtifactsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val allArtifacts = AGP.run { variant.allArtifacts } - assertNotNull(allArtifacts) - if (allArtifacts.isEmpty()) { - fail("allArtifacts is empty") - } - allArtifacts.forEach { (k, v) -> - println(" - $k => $v") - } - } - } -} - -class MinSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val minSdkVersion = AGP.run { variant.minSdkVersion } - assertNotNull(minSdkVersion) - assertEquals(MIN_SDK_VERSION, minSdkVersion.apiLevel) - } -} - -class TargetSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val targetSdkVersion = AGP.run { variant.targetSdkVersion } - assertNotNull(targetSdkVersion) - assertEquals(TARGET_SDK_VERSION, targetSdkVersion.apiLevel) - } -} - -class AarTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.library")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val aar = AGP.run { variant.aar }.search { - it.extension == "aar" - } - if (aar.isEmpty()) { - fail("aar is empty") - } - aar.forEach { - println(" - ${it.path}") - } - } - } -} - -class ApkTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val apk = AGP.run { variant.apk }.search { - it.extension == "apk" - } - if (apk.isEmpty()) { - fail("apk is empty") - } - apk.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedManifestsTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedManifests = AGP.run { variant.mergedManifests }.search { - it.name == "AndroidManifest.xml" - } - if (mergedManifests.isEmpty()) { - fail("mergedManifests is empty") - } - mergedManifests.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedResources = AGP.run { variant.mergedRes } - if (mergedResources.isEmpty) { - fail("mergedRes is empty") - } - mergedResources.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedAssetsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedAssets = AGP.run { variant.mergedAssets } - if (mergedAssets.isEmpty) { - fail("mergedAssets is empty") - } - mergedAssets.forEach { - println(" - ${it.path}") - } - } - } -} - -class ProcessedResTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val processedRes = AGP.run { variant.processedRes }.search { - it.extension == "ap_" - } - if (processedRes.isEmpty()) { - fail("processedRes is empty") - } - processedRes.forEach { - println(" - ${it.path}") - } - } - } -} - -class SymbolListTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val symbolList = AGP.run { variant.symbolList } - if (symbolList.isEmpty) { - fail("symbolList is empty") - } - symbolList.forEach { - println(" - ${it.path}") - } - } - } -} - -class SymbolListWithPackageNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val symbolListWithPackageName = AGP.run { variant.symbolListWithPackageName } - if (symbolListWithPackageName.isEmpty) { - fail("symbolListWithPackageName is empty") - } - symbolListWithPackageName.forEach { - println(" - ${it.path}") - } - } - } -} - -class AllClassesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val location = AGP.run { variant.allClasses }.files - assertTrue("ALL_CLASSES: $location", location::isNotEmpty) - assertTrue("No class file found at $location") { - location.search(File::isFile).isNotEmpty() - } - } - } -} - -class BuildToolsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val buildTools = AGP.run { variant.buildTools } - assertNotNull(buildTools) - BuildToolInfo.PathId.values().map { - it.name to buildTools.getPath(it) - }.forEach { (k, v) -> - println(" - $k => $v") - } - } -} diff --git a/booster-android-gradle-v4_0/src/integrationTest/resources/app.gradle b/booster-android-gradle-v4_0/src/integrationTest/resources/app.gradle deleted file mode 100644 index aa3c5f2d6..000000000 --- a/booster-android-gradle-v4_0/src/integrationTest/resources/app.gradle +++ /dev/null @@ -1,60 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } - dependencies { - classpath "com.android.tools.build:gradle:${project.android_gradle_version}" - classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { - exclude group: 'com.google.guava' - } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" - } -} - -apply plugin: 'com.android.application' -apply plugin: 'com.didiglobal.booster' -apply plugin: 'io.bootstage.testkit' - -android { - compileSdkVersion project.compile_sdk_version as Integer - buildToolsVersion project.build_tools_version - defaultConfig { - applicationId 'com.didiglobal.booster.test' - minSdkVersion project.min_sdk_version as Integer - targetSdkVersion project.target_sdk_version as Integer - versionCode 1 - versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - buildTypes { - debug { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - flavorDimensions 'lang' - productFlavors { - en { - dimension 'lang' - applicationIdSuffix '.en' - } - cn { - dimension 'lang' - applicationIdSuffix '.cn' - } - } - lintOptions { - checkReleaseBuilds false - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} diff --git a/booster-android-gradle-v4_0/src/integrationTest/resources/buildSrc/build.gradle b/booster-android-gradle-v4_0/src/integrationTest/resources/buildSrc/build.gradle deleted file mode 100644 index 79a9b104a..000000000 --- a/booster-android-gradle-v4_0/src/integrationTest/resources/buildSrc/build.gradle +++ /dev/null @@ -1,24 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} - -dependencies { - implementation "com.android.tools.build:gradle:${project.android_gradle_version}" - implementation("com.didiglobal.booster:booster-android-gradle-api:${project.booster_version}") { - exclude group: 'com.google.guava' - } - implementation "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" -} diff --git a/booster-android-gradle-v4_0/src/integrationTest/resources/lib.gradle b/booster-android-gradle-v4_0/src/integrationTest/resources/lib.gradle deleted file mode 100644 index adc9b1ca0..000000000 --- a/booster-android-gradle-v4_0/src/integrationTest/resources/lib.gradle +++ /dev/null @@ -1,57 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } - dependencies { - classpath "com.android.tools.build:gradle:${project.android_gradle_version}" - classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { - exclude group: 'com.google.guava' - } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" - } -} - -apply plugin: 'com.android.library' -apply plugin: 'com.didiglobal.booster' -apply plugin: 'io.bootstage.testkit' - -android { - compileSdkVersion project.compile_sdk_version as Integer - buildToolsVersion project.build_tools_version - defaultConfig { - minSdkVersion project.min_sdk_version as Integer - targetSdkVersion project.target_sdk_version as Integer - versionCode 1 - versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - buildTypes { - debug { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - flavorDimensions 'lang' - productFlavors { - en { - dimension 'lang' - } - cn { - dimension 'lang' - } - } - lintOptions { - checkReleaseBuilds false - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} diff --git a/booster-android-gradle-v4_0/src/integrationTest/resources/src/main/AndroidManifest.xml b/booster-android-gradle-v4_0/src/integrationTest/resources/src/main/AndroidManifest.xml deleted file mode 100644 index 30800c604..000000000 --- a/booster-android-gradle-v4_0/src/integrationTest/resources/src/main/AndroidManifest.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/booster-android-gradle-v4_0/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java b/booster-android-gradle-v4_0/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java deleted file mode 100644 index 0eb4ec7b4..000000000 --- a/booster-android-gradle-v4_0/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.didiglobal.booster.android.test; - -import android.app.Activity; - -public class MainActivity extends Activity { -} \ No newline at end of file diff --git a/booster-android-gradle-v4_0/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java b/booster-android-gradle-v4_0/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java deleted file mode 100644 index 3ecfb1507..000000000 --- a/booster-android-gradle-v4_0/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.didiglobal.booster.android.test; - -import android.app.Application; - -public class TestApplication extends Application { - -} \ No newline at end of file diff --git a/booster-android-gradle-v4_0/src/integrationTest/resources/src/main/res/values/strings.xml b/booster-android-gradle-v4_0/src/integrationTest/resources/src/main/res/values/strings.xml deleted file mode 100644 index 8b2247616..000000000 --- a/booster-android-gradle-v4_0/src/integrationTest/resources/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - Test - \ No newline at end of file diff --git a/booster-android-gradle-v4_0/src/main/kotlin/com/didiglobal/booster/android/gradle/v4_0/V40.kt b/booster-android-gradle-v4_0/src/main/kotlin/com/didiglobal/booster/android/gradle/v4_0/V40.kt deleted file mode 100644 index 41b87e81f..000000000 --- a/booster-android-gradle-v4_0/src/main/kotlin/com/didiglobal/booster/android/gradle/v4_0/V40.kt +++ /dev/null @@ -1,286 +0,0 @@ -package com.didiglobal.booster.android.gradle.v4_0 - -import com.android.build.api.transform.Context -import com.android.build.api.transform.QualifiedContent -import com.android.build.gradle.api.ApplicationVariant -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.LibraryVariant -import com.android.build.gradle.internal.pipeline.TransformManager -import com.android.build.gradle.internal.pipeline.TransformTask -import com.android.build.gradle.internal.publishing.AndroidArtifacts -import com.android.build.gradle.internal.scope.AnchorOutputType -import com.android.build.gradle.internal.scope.GlobalScope -import com.android.build.gradle.internal.scope.InternalArtifactType -import com.android.build.gradle.internal.scope.MultipleArtifactType -import com.android.build.gradle.internal.scope.SingleArtifactType -import com.android.build.gradle.internal.scope.VariantScope -import com.android.build.gradle.internal.variant.BaseVariantData -import com.android.builder.core.DefaultApiVersion -import com.android.builder.core.VariantType -import com.android.builder.model.ApiVersion -import com.android.sdklib.BuildToolInfo -import com.didiglobal.booster.gradle.AGPInterface -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.artifacts.ArtifactCollection -import org.gradle.api.artifacts.component.ComponentIdentifier -import org.gradle.api.artifacts.result.ResolvedArtifactResult -import org.gradle.api.artifacts.result.ResolvedDependencyResult -import org.gradle.api.file.FileCollection -import org.gradle.api.file.FileSystemLocation -import org.gradle.api.tasks.TaskProvider -import java.io.File -import java.util.TreeMap - -@Suppress("UnstableApiUsage") -internal val SINGLE_ARTIFACT_TYPES = arrayOf( - AnchorOutputType::class, - InternalArtifactType::class -).map { - it.sealedSubclasses -}.flatten().map { - it.objectInstance as SingleArtifactType -}.associateBy { - it.javaClass.simpleName -} - -@Suppress("UnstableApiUsage") -internal val MULTIPLE_ARTIFACT_TYPES = arrayOf( - MultipleArtifactType::class -).map { - it.sealedSubclasses -}.flatten().map { - it.objectInstance as MultipleArtifactType -}.associateBy { - it.javaClass.simpleName -} - -internal object V40 : AGPInterface { - - @Suppress("UnstableApiUsage") - private fun BaseVariant.getFinalArtifactFiles(type: SingleArtifactType): FileCollection { - return try { - project.objects.fileCollection().from(variantScope.artifacts.getOperations().get(type)) - } catch (e: Throwable) { - project.logger.warn(e.message, e) - project.objects.fileCollection().builtBy(variantScope.artifacts.getOperations().get(type)) - } - } - - @Suppress("UnstableApiUsage") - private fun BaseVariant.getFinalArtifactFiles(type: MultipleArtifactType): FileCollection { - return try { - project.objects.fileCollection().from(variantScope.artifacts.getOperations().getAll(type)) - } catch (e: Throwable) { - project.logger.warn(e.message, e) - project.objects.fileCollection().builtBy(variantScope.artifacts.getOperations().getAll(type)) - } - } - - override val scopeFullWithFeatures: MutableSet - get() = TransformManager.SCOPE_FULL_WITH_FEATURES - - override val scopeFullLibraryWithFeatures: MutableSet - get() = (TransformManager.SCOPE_FEATURES + QualifiedContent.Scope.PROJECT).toMutableSet() - - override val BaseVariant.project: Project - get() = globalScope.project - - override val BaseVariant.javaCompilerTaskProvider: TaskProvider - get() = javaCompileProvider - - override val BaseVariant.preBuildTaskProvider: TaskProvider - get() = preBuildProvider - - override val BaseVariant.assembleTaskProvider: TaskProvider - get() = assembleProvider - - override val BaseVariant.mergeAssetsTaskProvider: TaskProvider - get() = mergeAssetsProvider - - override val BaseVariant.mergeResourcesTaskProvider: TaskProvider - get() = try { - project.tasks.named(getTaskName("merge", "Resources")) - } catch (e: Throwable) { - mergeResourcesProvider - } - - override val BaseVariant.mergeNativeLibsTaskProvider: TaskProvider - get() = project.tasks.named(getTaskName("merge", "NativeLibs")) - - override val BaseVariant.processJavaResourcesTaskProvider: TaskProvider - get() = processJavaResourcesProvider - - override fun BaseVariant.getTaskName(prefix: String): String { - return variantScope.getTaskName(prefix) - } - - override fun BaseVariant.getTaskName(prefix: String, suffix: String): String { - return variantScope.getTaskName(prefix, suffix) - } - - override val BaseVariant.variantData: BaseVariantData - get() = javaClass.getDeclaredMethod("getVariantData").apply { - isAccessible = true - }.invoke(this) as BaseVariantData - - val BaseVariant.variantScope: VariantScope - get() = variantData.scope - - private val BaseVariant.globalScope: GlobalScope - get() = variantScope.globalScope - - override val BaseVariant.originalApplicationId: String - get() = variantData.variantDslInfo.originalApplicationId - - override val BaseVariant.hasDynamicFeature: Boolean - get() = globalScope.hasDynamicFeatures() - - override val BaseVariant.rawAndroidResources: FileCollection - get() = variantData.allRawAndroidResources - - override val BaseVariant.localAndroidResources: FileCollection - get() = variantData.androidResources.values.reduce { collection, file -> - collection.plus(file) - } - - override fun BaseVariant.getArtifactCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: AndroidArtifacts.ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): ArtifactCollection { - return variantScope.getArtifactCollection(configType, scope, artifactType) - } - - override fun BaseVariant.getArtifactFileCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: AndroidArtifacts.ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): FileCollection { - return variantScope.getArtifactFileCollection(configType, scope, artifactType) - } - - override val BaseVariant.allArtifacts: Map - get() = TreeMap().also { all -> - SINGLE_ARTIFACT_TYPES.entries.associateTo(all) { (name, type) -> - val artifacts: FileCollection by lazy { - getFinalArtifactFiles(type) - } - name to artifacts - } - MULTIPLE_ARTIFACT_TYPES.entries.associateTo(all) { (name, type) -> - val artifacts: FileCollection by lazy { - getFinalArtifactFiles(type) - } - name to artifacts - } - } - - override val BaseVariant.minSdkVersion: ApiVersion - get() = DefaultApiVersion(variantData.variantDslInfo.minSdkVersion.apiLevel) - - override val BaseVariant.targetSdkVersion: ApiVersion - get() = variantData.variantDslInfo.targetSdkVersion - - private val BaseVariant.variantType: VariantType - get() = variantScope.type - - override val BaseVariant.isApplication: Boolean - get() = variantType.isApk - - override val BaseVariant.isLibrary: Boolean - get() = variantType.isAar - - override val BaseVariant.isDynamicFeature: Boolean - get() = variantType.isDynamicFeature - - override val BaseVariant.aar: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.AAR) - - override val BaseVariant.apk: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.APK) - - override val BaseVariant.mergedManifests: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.MERGED_MANIFESTS) - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.LIBRARY_MANIFEST) - else -> TODO("Unsupported variant type: $variantType") - } - - override val BaseVariant.mergedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.MERGED_RES) - - override val BaseVariant.mergedNativeLibs: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.MERGED_NATIVE_LIBS) - - override val BaseVariant.mergedAssets: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.MERGED_ASSETS) - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.LIBRARY_ASSETS) - else -> TODO("Unsupported variant type: $variantType") - } - - override val BaseVariant.processedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.PROCESSED_RES) - - override val BaseVariant.symbolList: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.RUNTIME_SYMBOL_LIST) - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.COMPILE_SYMBOL_LIST) - else -> TODO("Unsupported variant type : $variantType") - } - - override val BaseVariant.symbolListWithPackageName: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.SYMBOL_LIST_WITH_PACKAGE_NAME) - - override val BaseVariant.dataBindingDependencyArtifacts: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.DATA_BINDING_DEPENDENCY_ARTIFACTS) - - override val BaseVariant.allClasses: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.JAVAC) + project.files("build${File.separator}tmp${File.separator}kotlin-classes${File.separator}${dirName}") - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.AAR_MAIN_JAR) - else -> project.files() - } - - override val BaseVariant.buildTools: BuildToolInfo - get() = globalScope.sdkComponents.buildToolInfoProvider.get() - - override val BaseVariant.isPrecompileDependenciesResourcesEnabled: Boolean - get() = variantScope.isPrecompileDependenciesResourcesEnabled - - override fun BaseVariant.getDependencies(transitive: Boolean, filter: (ComponentIdentifier) -> Boolean): Collection { - val all = getArtifactCollection( - AndroidArtifacts.ConsumedConfigType.RUNTIME_CLASSPATH, - AndroidArtifacts.ArtifactScope.ALL, - AndroidArtifacts.ArtifactType.CLASSES_JAR - ).filter { result -> - filter(result.id.componentIdentifier) - }.associateBy { - it.id.componentIdentifier.displayName - } - val result = if (!transitive) { - runtimeConfiguration.incoming.resolutionResult.root.dependencies.filterIsInstance().mapNotNull { - it.selected.id.displayName.takeIf { id -> id in all.keys } - }.associateWith { - all[it]!! - } - } else { - all - } - return result.values.toSet() - } - - override val Context.task: TransformTask - get() = javaClass.getDeclaredField("this$1").apply { - isAccessible = true - }.get(this).run { - javaClass.getDeclaredField("this$0").apply { - isAccessible = true - }.get(this) - } as TransformTask - - override val Project.aapt2Enabled: Boolean - get() = true - -} diff --git a/booster-android-gradle-v4_0/src/main/kotlin/com/didiglobal/booster/android/gradle/v4_0/V40Factory.kt b/booster-android-gradle-v4_0/src/main/kotlin/com/didiglobal/booster/android/gradle/v4_0/V40Factory.kt deleted file mode 100644 index 5ca2c0331..000000000 --- a/booster-android-gradle-v4_0/src/main/kotlin/com/didiglobal/booster/android/gradle/v4_0/V40Factory.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.didiglobal.booster.android.gradle.v4_0 - -import com.android.repository.Revision -import com.didiglobal.booster.gradle.AGPInterface -import com.didiglobal.booster.gradle.AGPInterfaceFactory -import com.google.auto.service.AutoService - -@AutoService(AGPInterfaceFactory::class) -class V40Factory : AGPInterfaceFactory { - - override val revision: Revision = Revision(4, 0, 0) - - override fun newAGPInterface(): AGPInterface = V40 - -} diff --git a/booster-android-gradle-v4_1/README.md b/booster-android-gradle-v4_1/README.md deleted file mode 100644 index d85cbf5a2..000000000 --- a/booster-android-gradle-v4_1/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# booster-android-gradle-v4_1 - -This module is an implementation of [booster-android-gradle-api](../booster-android-gradle-api) for Android gradle plugin above 4.1. - -本模块是 [booster-android-gradle-api](../booster-android-gradle-api) 针对 Android gradle plugin 4.1 以上版本的实现。 - diff --git a/booster-android-gradle-v4_1/build.gradle b/booster-android-gradle-v4_1/build.gradle deleted file mode 100644 index fc24cb46e..000000000 --- a/booster-android-gradle-v4_1/build.gradle +++ /dev/null @@ -1,19 +0,0 @@ -apply plugin: 'java-gradle-plugin' - -apply from: "$rootDir/gradle/booster.gradle" -apply from: "$rootDir/gradle/integration-test.gradle" -apply from: "$rootDir/gradle/functional-test.gradle" - -dependencies { - kapt 'com.google.auto.service:auto-service:1.0' - api 'com.google.auto.service:auto-service:1.0' - api project(':booster-android-gradle-compat') - compileOnly 'com.android.tools.build:gradle:4.1.0' - testImplementation 'com.android.tools.build:gradle:4.1.0' - testImplementation 'io.bootstage.testkit:testkit-gradle-plugin:1.4.0' - testImplementation project(':booster-build') -} - -gradlePlugin { - testSourceSets sourceSets.functionalTest, sourceSets.integrationTest -} \ No newline at end of file diff --git a/booster-android-gradle-v4_1/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v4_1/V41IntegrationTest.kt b/booster-android-gradle-v4_1/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v4_1/V41IntegrationTest.kt deleted file mode 100644 index ea804d3c8..000000000 --- a/booster-android-gradle-v4_1/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v4_1/V41IntegrationTest.kt +++ /dev/null @@ -1,481 +0,0 @@ -@file:Suppress("DEPRECATION") - -package com.didiglobal.booster.android.gradle.v4_1 - -import com.android.build.gradle.AppExtension -import com.android.build.gradle.BaseExtension -import com.android.build.gradle.LibraryExtension -import com.android.build.gradle.api.BaseVariant -import com.android.sdklib.BuildToolInfo -import com.didiglobal.booster.gradle.AGP -import com.didiglobal.booster.gradle.getAndroid -import com.didiglobal.booster.kotlinx.search -import io.bootstage.testkit.gradle.Case -import io.bootstage.testkit.gradle.TestCase -import io.bootstage.testkit.gradle.VariantTestCase -import io.bootstage.testkit.gradle.rules.GradleExecutor -import io.bootstage.testkit.gradle.rules.LocalProperties -import io.bootstage.testkit.gradle.rules.copyFromResource -import io.bootstage.testkit.gradle.rules.rule -import org.gradle.api.Project -import org.junit.Before -import org.junit.Rule -import org.junit.rules.TemporaryFolder -import org.junit.rules.TestRule -import java.io.File -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertNotNull -import kotlin.test.assertTrue -import kotlin.test.fail - -private val MIN_SDK_VERSION = System.getProperty("android.minsdk.version").toInt() - -private const val TARGET_SDK_VERSION = 26 - -private val ARGS = System.getProperty("gradle.args").split("\\s+".toRegex()) + listOf( - "-Pbooster_version=${Build.VERSION}", - "-Pandroid_gradle_version=4.1.0", - "-Pcompile_sdk_version=28", - "-Pbuild_tools_version=26.0.3", - "-Pmin_sdk_version=${MIN_SDK_VERSION}", - "-Ptarget_sdk_version=${TARGET_SDK_VERSION}" -) - -@Suppress("RemoveCurlyBracesFromTemplate", "FunctionName") -abstract class V41IntegrationTest(val isLib: Boolean) { - - private val projectDir = TemporaryFolder() - - @get:Rule - val ruleChain: TestRule = rule(projectDir) { - rule(LocalProperties(projectDir::getRoot)) { - GradleExecutor(projectDir::getRoot, "6.5", *ARGS.toTypedArray()) - } - } - - @Before - fun setup() { - projectDir.copyFromResource("${if (isLib) "lib" else "app"}.gradle", "build.gradle") - projectDir.copyFromResource("buildSrc") - projectDir.copyFromResource("src") - projectDir.newFile("gradle.properties").writeText("org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=2g") - assertEquals(4, AGP.revision.major) - assertEquals(1, AGP.revision.minor) - } - - @Test - @Case(ScopeFullWithFeaturesTest::class) - fun `test AGPInterface#scopeFullWithFeatures`() = Unit - - @Test - @Case(ScopeFullLibraryWithFeaturesTest::class) - fun `test AGPInterface#scopeFullLibraryWithFeatures`() = Unit - - @Test - @Case(ProjectTest::class) - fun `test AGPInterface#project`() = Unit - - @Test - @Case(JavaCompilerTaskTestUnit::class) - fun `test AGPInterface#javaCompilerTask`() = Unit - - @Test - @Case(PreBuildTaskTestUnit::class) - fun `test AGPInterface#preBuildTask`() = Unit - - @Test - @Case(AssembleTaskTestUnit::class) - fun `test AGPInterface#assembleTask`() = Unit - - @Test - @Case(MergeAssetsTaskTestUnit::class) - fun `test AGPInterface#mergeAssetsTask`() = Unit - - @Test - @Case(MergeResourcesTaskTestUnit::class) - fun `test AGPInterface#mergeResources`() = Unit - - @Test - @Case(GetTaskNameTestUnit::class) - fun `test AGPInterface#getTaskName(String)`() = Unit - - @Test - @Case(GetTaskName2TestUnit::class) - fun `test AGPInterface#getTaskName(String, String)`() = Unit - - @Test - @Case(VariantDataTestUnit::class) - fun `test AGPInterface#variantData`() = Unit - - @Test - @Case(OriginalApplicationIdTestUnit::class) - fun `test AGPInterface#originalApplicationId`() = Unit - - @Test - @Case(HasDynamicFeatureTestUnit::class) - fun `test AGPInterface#hasDynamicFeature`() = Unit - - @Test - @Case(RawAndroidResourcesTestUnit::class) - fun `test AGPInterface#rawAndroidResources`() = Unit - - @Test - @Case(AllArtifactsTestUnit::class) - fun `test AGPInterface#allArtifacts`() = Unit - - @Test - @Case(MinSdkVersionTestUnit::class) - fun `test AGPInterface#minSdkVersion`() = Unit - - @Test - @Case(TargetSdkVersionTestUnit::class) - fun `test AGPInterface#targetSdkVersion`() = Unit - - @Test - @Case(AarTestUnit::class) - fun `test AGPInterface#aar`() = Unit - - @Test - @Case(ApkTestUnit::class) - fun `test AGPInterface#apk`() = Unit - - @Test - @Case(MergedManifestsTestUnit::class) - fun `test AGPInterface#mergedManifests`() = Unit - - @Test - @Case(MergedResourcesTestUnit::class) - fun `test AGPInterface#mergedRes`() = Unit - - @Test - @Case(MergedAssetsTestUnit::class) - fun `test AGPInterface#mergedAssets`() = Unit - - @Test - @Case(ProcessedResTestUnit::class) - fun `test AGPInterface#processedRes`() = Unit - - @Test - @Case(SymbolListTestUnit::class) - fun `test AGPInterface#symbolList`() = Unit - - @Test - @Case(SymbolListWithPackageNameTestUnit::class) - fun `test AGPInterface#symbolListWithPackageName`() = Unit - - @Test - @Case(AllClassesTestUnit::class) - fun `test AGPInterface#allClasses`() = Unit - - @Test - @Case(BuildToolsTestUnit::class) - fun `test AGPInterface#buildTools`() = Unit - -} - -class V41AppIntegrationTest : V41IntegrationTest(false) - -class V41LibIntegrationTest : V41IntegrationTest(true) - -class ScopeFullWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("PROJECT,SUB_PROJECTS,EXTERNAL_LIBRARIES,FEATURES", AGP.scopeFullWithFeatures.joinToString(",")) - } -} - -class ScopeFullLibraryWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("FEATURES,PROJECT", AGP.scopeFullLibraryWithFeatures.joinToString(",")) - } -} - -class ProjectTest : TestCase { - override fun apply(project: Project) { - val assert: (BaseVariant) -> Unit = { variant -> - assertEquals(project, AGP.run { variant.project }) - } - project.afterEvaluate { - when (val android = project.getAndroid()) { - is AppExtension -> android.applicationVariants.forEach(assert) - is LibraryExtension -> android.libraryVariants.forEach(assert) - } - } - } -} - -class JavaCompilerTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.javaCompilerTask }) - } -} - -class PreBuildTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.preBuildTask }) - } -} - -class AssembleTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.assembleTask }) - } -} - -class MergeAssetsTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeAssetsTask }) - } -} - -class MergeResourcesTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeResourcesTask }) - } -} - -class GetTaskNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("assemble${variant.name.capitalize()}", AGP.run { variant.getTaskName("assemble") }) - } -} - - -class GetTaskName2TestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("merge${variant.name.capitalize()}Resources", AGP.run { variant.getTaskName("merge", "Resources") }) - } -} - -class VariantDataTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.variantData }) - } -} - -class OriginalApplicationIdTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.originalApplicationId }) - } -} - -class HasDynamicFeatureTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertFalse(AGP.run { variant.hasDynamicFeature }) - } -} - -class RawAndroidResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val rawAndroidResources = AGP.run { variant.rawAndroidResources } - assertNotNull(rawAndroidResources) - if (rawAndroidResources.isEmpty) { - fail("rawAndroidResources is empty") - } - rawAndroidResources.forEach { - println(" - ${it.path}") - } - } - } -} - -class AllArtifactsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val allArtifacts = AGP.run { variant.allArtifacts } - assertNotNull(allArtifacts) - if (allArtifacts.isEmpty()) { - fail("allArtifacts is empty") - } - allArtifacts.forEach { (k, v) -> - println(" - $k => $v") - } - } - } -} - -class MinSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val minSdkVersion = AGP.run { variant.minSdkVersion } - assertNotNull(minSdkVersion) - assertEquals(MIN_SDK_VERSION, minSdkVersion.apiLevel) - } -} - -class TargetSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val targetSdkVersion = AGP.run { variant.targetSdkVersion } - assertNotNull(targetSdkVersion) - assertEquals(TARGET_SDK_VERSION, targetSdkVersion.apiLevel) - } -} - -class AarTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.library")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val aar = AGP.run { variant.aar }.search { - it.extension == "aar" - } - if (aar.isEmpty()) { - fail("aar is empty") - } - aar.forEach { - println(" - ${it.path}") - } - } - } -} - -class ApkTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val apk = AGP.run { variant.apk }.search { - it.extension == "apk" - } - if (apk.isEmpty()) { - fail("apk is empty") - } - apk.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedManifestsTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedManifests = AGP.run { variant.mergedManifests }.search { - it.name == "AndroidManifest.xml" - } - if (mergedManifests.isEmpty()) { - fail("mergedManifests is empty") - } - mergedManifests.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedResources = AGP.run { variant.mergedRes } - if (mergedResources.isEmpty) { - fail("mergedRes is empty") - } - mergedResources.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedAssetsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedAssets = AGP.run { variant.mergedAssets } - if (mergedAssets.isEmpty) { - fail("mergedAssets is empty") - } - mergedAssets.forEach { - println(" - ${it.path}") - } - } - } -} - -class ProcessedResTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val processedRes = AGP.run { variant.processedRes }.search { - it.extension == "ap_" - } - if (processedRes.isEmpty()) { - fail("processedRes is empty") - } - processedRes.forEach { - println(" - ${it.path}") - } - } - } -} - -class SymbolListTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val symbolList = AGP.run { variant.symbolList } - if (symbolList.isEmpty) { - fail("symbolList is empty") - } - symbolList.forEach { - println(" - ${it.path}") - } - } - } -} - -class SymbolListWithPackageNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val symbolListWithPackageName = AGP.run { variant.symbolListWithPackageName } - if (symbolListWithPackageName.isEmpty) { - fail("symbolListWithPackageName is empty") - } - symbolListWithPackageName.forEach { - println(" - ${it.path}") - } - } - } -} - -class AllClassesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val location = AGP.run { variant.allClasses }.files - assertTrue("ALL_CLASSES: $location", location::isNotEmpty) - assertTrue("No class file found at $location") { - location.search(File::isFile).isNotEmpty() - } - } - } -} - -class BuildToolsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val buildTools = AGP.run { variant.buildTools } - assertNotNull(buildTools) - BuildToolInfo.PathId.values().map { - it.name to buildTools.getPath(it) - }.forEach { (k, v) -> - println(" - $k => $v") - } - } -} diff --git a/booster-android-gradle-v4_1/src/integrationTest/resources/app.gradle b/booster-android-gradle-v4_1/src/integrationTest/resources/app.gradle deleted file mode 100644 index aa3c5f2d6..000000000 --- a/booster-android-gradle-v4_1/src/integrationTest/resources/app.gradle +++ /dev/null @@ -1,60 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } - dependencies { - classpath "com.android.tools.build:gradle:${project.android_gradle_version}" - classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { - exclude group: 'com.google.guava' - } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" - } -} - -apply plugin: 'com.android.application' -apply plugin: 'com.didiglobal.booster' -apply plugin: 'io.bootstage.testkit' - -android { - compileSdkVersion project.compile_sdk_version as Integer - buildToolsVersion project.build_tools_version - defaultConfig { - applicationId 'com.didiglobal.booster.test' - minSdkVersion project.min_sdk_version as Integer - targetSdkVersion project.target_sdk_version as Integer - versionCode 1 - versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - buildTypes { - debug { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - flavorDimensions 'lang' - productFlavors { - en { - dimension 'lang' - applicationIdSuffix '.en' - } - cn { - dimension 'lang' - applicationIdSuffix '.cn' - } - } - lintOptions { - checkReleaseBuilds false - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} diff --git a/booster-android-gradle-v4_1/src/integrationTest/resources/buildSrc/build.gradle b/booster-android-gradle-v4_1/src/integrationTest/resources/buildSrc/build.gradle deleted file mode 100644 index 79a9b104a..000000000 --- a/booster-android-gradle-v4_1/src/integrationTest/resources/buildSrc/build.gradle +++ /dev/null @@ -1,24 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} - -dependencies { - implementation "com.android.tools.build:gradle:${project.android_gradle_version}" - implementation("com.didiglobal.booster:booster-android-gradle-api:${project.booster_version}") { - exclude group: 'com.google.guava' - } - implementation "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" -} diff --git a/booster-android-gradle-v4_1/src/integrationTest/resources/lib.gradle b/booster-android-gradle-v4_1/src/integrationTest/resources/lib.gradle deleted file mode 100644 index adc9b1ca0..000000000 --- a/booster-android-gradle-v4_1/src/integrationTest/resources/lib.gradle +++ /dev/null @@ -1,57 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } - dependencies { - classpath "com.android.tools.build:gradle:${project.android_gradle_version}" - classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { - exclude group: 'com.google.guava' - } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" - } -} - -apply plugin: 'com.android.library' -apply plugin: 'com.didiglobal.booster' -apply plugin: 'io.bootstage.testkit' - -android { - compileSdkVersion project.compile_sdk_version as Integer - buildToolsVersion project.build_tools_version - defaultConfig { - minSdkVersion project.min_sdk_version as Integer - targetSdkVersion project.target_sdk_version as Integer - versionCode 1 - versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - buildTypes { - debug { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - flavorDimensions 'lang' - productFlavors { - en { - dimension 'lang' - } - cn { - dimension 'lang' - } - } - lintOptions { - checkReleaseBuilds false - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} diff --git a/booster-android-gradle-v4_1/src/integrationTest/resources/src/main/AndroidManifest.xml b/booster-android-gradle-v4_1/src/integrationTest/resources/src/main/AndroidManifest.xml deleted file mode 100644 index 30800c604..000000000 --- a/booster-android-gradle-v4_1/src/integrationTest/resources/src/main/AndroidManifest.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/booster-android-gradle-v4_1/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java b/booster-android-gradle-v4_1/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java deleted file mode 100644 index 0eb4ec7b4..000000000 --- a/booster-android-gradle-v4_1/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.didiglobal.booster.android.test; - -import android.app.Activity; - -public class MainActivity extends Activity { -} \ No newline at end of file diff --git a/booster-android-gradle-v4_1/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java b/booster-android-gradle-v4_1/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java deleted file mode 100644 index 3ecfb1507..000000000 --- a/booster-android-gradle-v4_1/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.didiglobal.booster.android.test; - -import android.app.Application; - -public class TestApplication extends Application { - -} \ No newline at end of file diff --git a/booster-android-gradle-v4_1/src/integrationTest/resources/src/main/res/values/strings.xml b/booster-android-gradle-v4_1/src/integrationTest/resources/src/main/res/values/strings.xml deleted file mode 100644 index 8b2247616..000000000 --- a/booster-android-gradle-v4_1/src/integrationTest/resources/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - Test - \ No newline at end of file diff --git a/booster-android-gradle-v4_1/src/main/kotlin/com/didiglobal/booster/android/gradle/v4_1/V41.kt b/booster-android-gradle-v4_1/src/main/kotlin/com/didiglobal/booster/android/gradle/v4_1/V41.kt deleted file mode 100644 index f4b07c51b..000000000 --- a/booster-android-gradle-v4_1/src/main/kotlin/com/didiglobal/booster/android/gradle/v4_1/V41.kt +++ /dev/null @@ -1,299 +0,0 @@ -package com.didiglobal.booster.android.gradle.v4_1 - -import com.android.build.api.artifact.Artifact -import com.android.build.api.artifact.ArtifactType -import com.android.build.api.artifact.MultipleArtifactType -import com.android.build.api.artifact.impl.ArtifactsImpl -import com.android.build.api.component.impl.ComponentPropertiesImpl -import com.android.build.api.transform.Context -import com.android.build.api.transform.QualifiedContent -import com.android.build.gradle.api.ApplicationVariant -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.LibraryVariant -import com.android.build.gradle.internal.api.BaseVariantImpl -import com.android.build.gradle.internal.pipeline.TransformManager -import com.android.build.gradle.internal.pipeline.TransformTask -import com.android.build.gradle.internal.publishing.AndroidArtifacts -import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactScope -import com.android.build.gradle.internal.scope.AnchorOutputType -import com.android.build.gradle.internal.scope.GlobalScope -import com.android.build.gradle.internal.scope.InternalArtifactType -import com.android.build.gradle.internal.scope.InternalMultipleArtifactType -import com.android.build.gradle.internal.scope.VariantScope -import com.android.build.gradle.internal.variant.BaseVariantData -import com.android.builder.core.DefaultApiVersion -import com.android.builder.core.VariantType -import com.android.builder.model.ApiVersion -import com.android.sdklib.BuildToolInfo -import com.didiglobal.booster.gradle.AGPInterface -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.artifacts.ArtifactCollection -import org.gradle.api.artifacts.component.ComponentIdentifier -import org.gradle.api.artifacts.result.ResolvedArtifactResult -import org.gradle.api.artifacts.result.ResolvedDependencyResult -import org.gradle.api.file.FileCollection -import org.gradle.api.file.FileSystemLocation -import org.gradle.api.tasks.TaskProvider -import java.io.File -import java.util.TreeMap - -@Suppress("UnstableApiUsage") -private val SINGLE_ARTIFACT_TYPES = arrayOf( - ArtifactType::class, - AnchorOutputType::class, - InternalArtifactType::class -).map { - it.sealedSubclasses -}.flatten().map { - it.objectInstance as Artifact.SingleArtifact -}.associateBy { - it.javaClass.simpleName -} - -@Suppress("UnstableApiUsage") -private val MULTIPLE_ARTIFACT_TYPES = arrayOf( - MultipleArtifactType::class, - InternalMultipleArtifactType::class -).map { - it.sealedSubclasses -}.flatten().map { - it.objectInstance as Artifact.MultipleArtifact -}.associateBy { - it.javaClass.simpleName -} - -internal object V41 : AGPInterface { - - private val BaseVariant.componentProperties: ComponentPropertiesImpl - get() = BaseVariantImpl::class.java.getDeclaredField("componentProperties").apply { - isAccessible = true - }.get(this) as ComponentPropertiesImpl - - @Suppress("UnstableApiUsage") - private fun BaseVariant.getFinalArtifactFiles(type: Artifact.SingleArtifact): FileCollection { - return try { - project.objects.fileCollection().from(artifacts.get(type)) - } catch (e: Throwable) { - project.logger.warn(e.message, e) - project.objects.fileCollection().builtBy(artifacts.get(type)) - } - } - - @Suppress("UnstableApiUsage") - private fun BaseVariant.getFinalArtifactFiles(type: Artifact.MultipleArtifact): FileCollection { - return try { - project.objects.fileCollection().from(artifacts.getAll(type)) - } catch (e: Throwable) { - project.logger.warn(e.message, e) - project.objects.fileCollection().builtBy(artifacts.getAll(type)) - } - } - - @Suppress("UnstableApiUsage") - private val BaseVariant.artifacts: ArtifactsImpl - get() = componentProperties.artifacts - - override val scopeFullWithFeatures: MutableSet - get() = TransformManager.SCOPE_FULL_WITH_FEATURES - - override val scopeFullLibraryWithFeatures: MutableSet - get() = (TransformManager.SCOPE_FEATURES + QualifiedContent.Scope.PROJECT).toMutableSet() - - override val BaseVariant.project: Project - get() = globalScope.project - - override val BaseVariant.javaCompilerTaskProvider: TaskProvider - get() = javaCompileProvider - - override val BaseVariant.preBuildTaskProvider: TaskProvider - get() = preBuildProvider - - override val BaseVariant.assembleTaskProvider: TaskProvider - get() = assembleProvider - - override val BaseVariant.mergeAssetsTaskProvider: TaskProvider - get() = mergeAssetsProvider - - override val BaseVariant.mergeResourcesTaskProvider: TaskProvider - get() = try { - project.tasks.named(getTaskName("merge", "Resources")) - } catch (e: Throwable) { - mergeResourcesProvider - } - - override val BaseVariant.mergeNativeLibsTaskProvider: TaskProvider - get() = project.tasks.named(getTaskName("merge", "NativeLibs")) - - override val BaseVariant.processJavaResourcesTaskProvider: TaskProvider - get() = processJavaResourcesProvider - - override fun BaseVariant.getTaskName(prefix: String): String { - return componentProperties.computeTaskName(prefix) - } - - override fun BaseVariant.getTaskName(prefix: String, suffix: String): String { - return componentProperties.computeTaskName(prefix, suffix) - } - - override val BaseVariant.variantData: BaseVariantData - get() = javaClass.getDeclaredMethod("getVariantData").apply { - isAccessible = true - }.invoke(this) as BaseVariantData - - val BaseVariant.variantScope: VariantScope - get() = componentProperties.variantScope - - private val BaseVariant.globalScope: GlobalScope - get() = componentProperties.globalScope - - override val BaseVariant.originalApplicationId: String - get() = componentProperties.variantDslInfo.packageName.get() - - override val BaseVariant.hasDynamicFeature: Boolean - get() = globalScope.hasDynamicFeatures() - - override val BaseVariant.rawAndroidResources: FileCollection - get() = componentProperties.variantData.allRawAndroidResources - - override val BaseVariant.localAndroidResources: FileCollection - get() = componentProperties.variantData.androidResources.values.reduce { collection, file -> - collection.plus(file) - } - - override fun BaseVariant.getArtifactCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): ArtifactCollection { - return componentProperties.variantDependencies.getArtifactCollection(configType, scope, artifactType) - } - - override fun BaseVariant.getArtifactFileCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): FileCollection { - return componentProperties.variantDependencies.getArtifactFileCollection(configType, scope, artifactType) - } - - override val BaseVariant.allArtifacts: Map - get() = TreeMap().also { all -> - SINGLE_ARTIFACT_TYPES.entries.associateTo(all) { (name, type) -> - val artifacts: FileCollection by lazy { - getFinalArtifactFiles(type) - } - name to artifacts - } - MULTIPLE_ARTIFACT_TYPES.entries.associateTo(all) { (name, type) -> - val artifacts: FileCollection by lazy { - getFinalArtifactFiles(type) - } - name to artifacts - } - } - - override val BaseVariant.minSdkVersion: ApiVersion - get() = DefaultApiVersion(componentProperties.minSdkVersion.apiLevel) - - override val BaseVariant.targetSdkVersion: ApiVersion - get() = componentProperties.targetSdkVersion - - private val BaseVariant.variantType: VariantType - get() = componentProperties.variantType - - override val BaseVariant.isApplication: Boolean - get() = variantType.isApk - - override val BaseVariant.isLibrary: Boolean - get() = variantType.isAar - - override val BaseVariant.isDynamicFeature: Boolean - get() = variantType.isDynamicFeature - - override val BaseVariant.aar: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.AAR) - - override val BaseVariant.apk: FileCollection - get() = getFinalArtifactFiles(ArtifactType.APK) - - override val BaseVariant.mergedManifests: FileCollection - get() = getFinalArtifactFiles(ArtifactType.MERGED_MANIFEST) - - override val BaseVariant.mergedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.MERGED_RES) - - override val BaseVariant.mergedNativeLibs: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.MERGED_NATIVE_LIBS) - - override val BaseVariant.mergedAssets: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.MERGED_ASSETS) - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.LIBRARY_ASSETS) - else -> TODO("Unsupported variant type: $variantType") - } - - override val BaseVariant.processedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.PROCESSED_RES) - - override val BaseVariant.symbolList: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.RUNTIME_SYMBOL_LIST) - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.COMPILE_SYMBOL_LIST) - else -> TODO("Unsupported variant type : $variantType") - } - - override val BaseVariant.symbolListWithPackageName: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.SYMBOL_LIST_WITH_PACKAGE_NAME) - - override val BaseVariant.dataBindingDependencyArtifacts: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.DATA_BINDING_DEPENDENCY_ARTIFACTS) - - override val BaseVariant.allClasses: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.JAVAC) + project.files("build${File.separator}tmp${File.separator}kotlin-classes${File.separator}${dirName}") - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.AAR_MAIN_JAR) - else -> project.files() - } - - override val BaseVariant.buildTools: BuildToolInfo - get() = globalScope.sdkComponents.get().buildToolInfoProvider.get() - - override val BaseVariant.isPrecompileDependenciesResourcesEnabled: Boolean - get() = variantScope.isPrecompileDependenciesResourcesEnabled - - override fun BaseVariant.getDependencies(transitive: Boolean, filter: (ComponentIdentifier) -> Boolean): Collection { - val all = getArtifactCollection( - AndroidArtifacts.ConsumedConfigType.RUNTIME_CLASSPATH, - AndroidArtifacts.ArtifactScope.ALL, - AndroidArtifacts.ArtifactType.CLASSES_JAR - ).filter { result -> - filter(result.id.componentIdentifier) - }.associateBy { - it.id.componentIdentifier.displayName - } - val result = if (!transitive) { - runtimeConfiguration.incoming.resolutionResult.root.dependencies.filterIsInstance().mapNotNull { - it.selected.id.displayName.takeIf { id -> id in all.keys } - }.associateWith { - all[it]!! - } - } else { - all - } - return result.values.toSet() - } - - override val Context.task: TransformTask - get() = javaClass.getDeclaredField("this$1").apply { - isAccessible = true - }.get(this).run { - javaClass.getDeclaredField("this$0").apply { - isAccessible = true - }.get(this) - } as TransformTask - - override val Project.aapt2Enabled: Boolean - get() = true - -} diff --git a/booster-android-gradle-v4_1/src/main/kotlin/com/didiglobal/booster/android/gradle/v4_1/V41Factory.kt b/booster-android-gradle-v4_1/src/main/kotlin/com/didiglobal/booster/android/gradle/v4_1/V41Factory.kt deleted file mode 100644 index 9fb0adcb3..000000000 --- a/booster-android-gradle-v4_1/src/main/kotlin/com/didiglobal/booster/android/gradle/v4_1/V41Factory.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.didiglobal.booster.android.gradle.v4_1 - -import com.android.repository.Revision -import com.didiglobal.booster.gradle.AGPInterface -import com.didiglobal.booster.gradle.AGPInterfaceFactory -import com.google.auto.service.AutoService - -@AutoService(AGPInterfaceFactory::class) -class V41Factory : AGPInterfaceFactory { - - override val revision: Revision = Revision(4, 1, 0) - - override fun newAGPInterface(): AGPInterface = V41 - -} diff --git a/booster-android-gradle-v4_2/README.md b/booster-android-gradle-v4_2/README.md deleted file mode 100644 index 5e8eec8ea..000000000 --- a/booster-android-gradle-v4_2/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# booster-android-gradle-v4_2 - -This module is an implementation of [booster-android-gradle-api](../booster-android-gradle-api) for Android gradle plugin above 4.2. - -本模块是 [booster-android-gradle-api](../booster-android-gradle-api) 针对 Android gradle plugin 4.2 以上版本的实现。 - diff --git a/booster-android-gradle-v4_2/build.gradle b/booster-android-gradle-v4_2/build.gradle deleted file mode 100644 index c07f4fbe9..000000000 --- a/booster-android-gradle-v4_2/build.gradle +++ /dev/null @@ -1,19 +0,0 @@ -apply plugin: 'java-gradle-plugin' - -apply from: "$rootDir/gradle/booster.gradle" -apply from: "$rootDir/gradle/integration-test.gradle" -apply from: "$rootDir/gradle/functional-test.gradle" - -dependencies { - kapt 'com.google.auto.service:auto-service:1.0' - api 'com.google.auto.service:auto-service:1.0' - api project(':booster-android-gradle-compat') - compileOnly 'com.android.tools.build:gradle:4.2.0' - testImplementation 'com.android.tools.build:gradle:4.2.0' - testImplementation 'io.bootstage.testkit:testkit-gradle-plugin:1.1.0' - testImplementation project(':booster-build') -} - -gradlePlugin { - testSourceSets sourceSets.functionalTest, sourceSets.integrationTest -} \ No newline at end of file diff --git a/booster-android-gradle-v4_2/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v4_2/V42IntegrationTest.kt b/booster-android-gradle-v4_2/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v4_2/V42IntegrationTest.kt deleted file mode 100644 index 0c04f7814..000000000 --- a/booster-android-gradle-v4_2/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v4_2/V42IntegrationTest.kt +++ /dev/null @@ -1,481 +0,0 @@ -@file:Suppress("DEPRECATION") - -package com.didiglobal.booster.android.gradle.v4_2 - -import com.android.build.gradle.AppExtension -import com.android.build.gradle.BaseExtension -import com.android.build.gradle.LibraryExtension -import com.android.build.gradle.api.BaseVariant -import com.android.sdklib.BuildToolInfo -import com.didiglobal.booster.gradle.AGP -import com.didiglobal.booster.gradle.getAndroid -import com.didiglobal.booster.kotlinx.search -import io.bootstage.testkit.gradle.Case -import io.bootstage.testkit.gradle.TestCase -import io.bootstage.testkit.gradle.VariantTestCase -import io.bootstage.testkit.gradle.rules.GradleExecutor -import io.bootstage.testkit.gradle.rules.LocalProperties -import io.bootstage.testkit.gradle.rules.copyFromResource -import io.bootstage.testkit.gradle.rules.rule -import org.gradle.api.Project -import org.junit.Before -import org.junit.Rule -import org.junit.rules.TemporaryFolder -import org.junit.rules.TestRule -import java.io.File -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertNotNull -import kotlin.test.assertTrue -import kotlin.test.fail - -private val MIN_SDK_VERSION = System.getProperty("android.minsdk.version").toInt() - -private const val TARGET_SDK_VERSION = 26 - -private val ARGS = System.getProperty("gradle.args").split("\\s+".toRegex()) + listOf( - "-Pbooster_version=${Build.VERSION}", - "-Pandroid_gradle_version=4.2.1", - "-Pcompile_sdk_version=28", - "-Pbuild_tools_version=26.0.3", - "-Pmin_sdk_version=${MIN_SDK_VERSION}", - "-Ptarget_sdk_version=${TARGET_SDK_VERSION}" -) - -@Suppress("RemoveCurlyBracesFromTemplate", "FunctionName") -abstract class V42IntegrationTest(val isLib: Boolean) { - - private val projectDir = TemporaryFolder() - - @get:Rule - val ruleChain: TestRule = rule(projectDir) { - rule(LocalProperties(projectDir::getRoot)) { - GradleExecutor(projectDir::getRoot, "6.7.1", *ARGS.toTypedArray()) - } - } - - @Before - fun setup() { - projectDir.copyFromResource("${if (isLib) "lib" else "app"}.gradle", "build.gradle") - projectDir.copyFromResource("buildSrc") - projectDir.copyFromResource("src") - projectDir.newFile("gradle.properties").writeText("org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=2g") - assertEquals(4, AGP.revision.major) - assertEquals(2, AGP.revision.minor) - } - - @Test - @Case(ScopeFullWithFeaturesTest::class) - fun `test AGPInterface#scopeFullWithFeatures`() = Unit - - @Test - @Case(ScopeFullLibraryWithFeaturesTest::class) - fun `test AGPInterface#scopeFullLibraryWithFeatures`() = Unit - - @Test - @Case(ProjectTest::class) - fun `test AGPInterface#project`() = Unit - - @Test - @Case(JavaCompilerTaskTestUnit::class) - fun `test AGPInterface#javaCompilerTask`() = Unit - - @Test - @Case(PreBuildTaskTestUnit::class) - fun `test AGPInterface#preBuildTask`() = Unit - - @Test - @Case(AssembleTaskTestUnit::class) - fun `test AGPInterface#assembleTask`() = Unit - - @Test - @Case(MergeAssetsTaskTestUnit::class) - fun `test AGPInterface#mergeAssetsTask`() = Unit - - @Test - @Case(MergeResourcesTaskTestUnit::class) - fun `test AGPInterface#mergeResources`() = Unit - - @Test - @Case(GetTaskNameTestUnit::class) - fun `test AGPInterface#getTaskName(String)`() = Unit - - @Test - @Case(GetTaskName2TestUnit::class) - fun `test AGPInterface#getTaskName(String, String)`() = Unit - - @Test - @Case(VariantDataTestUnit::class) - fun `test AGPInterface#variantData`() = Unit - - @Test - @Case(OriginalApplicationIdTestUnit::class) - fun `test AGPInterface#originalApplicationId`() = Unit - - @Test - @Case(HasDynamicFeatureTestUnit::class) - fun `test AGPInterface#hasDynamicFeature`() = Unit - - @Test - @Case(RawAndroidResourcesTestUnit::class) - fun `test AGPInterface#rawAndroidResources`() = Unit - - @Test - @Case(AllArtifactsTestUnit::class) - fun `test AGPInterface#allArtifacts`() = Unit - - @Test - @Case(MinSdkVersionTestUnit::class) - fun `test AGPInterface#minSdkVersion`() = Unit - - @Test - @Case(TargetSdkVersionTestUnit::class) - fun `test AGPInterface#targetSdkVersion`() = Unit - - @Test - @Case(AarTestUnit::class) - fun `test AGPInterface#aar`() = Unit - - @Test - @Case(ApkTestUnit::class) - fun `test AGPInterface#apk`() = Unit - - @Test - @Case(MergedManifestsTestUnit::class) - fun `test AGPInterface#mergedManifests`() = Unit - - @Test - @Case(MergedResourcesTestUnit::class) - fun `test AGPInterface#mergedRes`() = Unit - - @Test - @Case(MergedAssetsTestUnit::class) - fun `test AGPInterface#mergedAssets`() = Unit - - @Test - @Case(ProcessedResTestUnit::class) - fun `test AGPInterface#processedRes`() = Unit - - @Test - @Case(SymbolListTestUnit::class) - fun `test AGPInterface#symbolList`() = Unit - - @Test - @Case(SymbolListWithPackageNameTestUnit::class) - fun `test AGPInterface#symbolListWithPackageName`() = Unit - - @Test - @Case(AllClassesTestUnit::class) - fun `test AGPInterface#allClasses`() = Unit - - @Test - @Case(BuildToolsTestUnit::class) - fun `test AGPInterface#buildTools`() = Unit - -} - -class V42AppIntegrationTest : V42IntegrationTest(false) - -class V42LibIntegrationTest : V42IntegrationTest(true) - -class ScopeFullWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("PROJECT,SUB_PROJECTS,EXTERNAL_LIBRARIES,FEATURES", AGP.scopeFullWithFeatures.joinToString(",")) - } -} - -class ScopeFullLibraryWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("FEATURES,PROJECT", AGP.scopeFullLibraryWithFeatures.joinToString(",")) - } -} - -class ProjectTest : TestCase { - override fun apply(project: Project) { - val assert: (BaseVariant) -> Unit = { variant -> - assertEquals(project, AGP.run { variant.project }) - } - project.afterEvaluate { - when (val android = project.getAndroid()) { - is AppExtension -> android.applicationVariants.forEach(assert) - is LibraryExtension -> android.libraryVariants.forEach(assert) - } - } - } -} - -class JavaCompilerTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.javaCompilerTask }) - } -} - -class PreBuildTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.preBuildTask }) - } -} - -class AssembleTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.assembleTask }) - } -} - -class MergeAssetsTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeAssetsTask }) - } -} - -class MergeResourcesTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeResourcesTask }) - } -} - -class GetTaskNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("assemble${variant.name.capitalize()}", AGP.run { variant.getTaskName("assemble") }) - } -} - - -class GetTaskName2TestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("merge${variant.name.capitalize()}Resources", AGP.run { variant.getTaskName("merge", "Resources") }) - } -} - -class VariantDataTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.variantData }) - } -} - -class OriginalApplicationIdTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.originalApplicationId }) - } -} - -class HasDynamicFeatureTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertFalse(AGP.run { variant.hasDynamicFeature }) - } -} - -class RawAndroidResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val rawAndroidResources = AGP.run { variant.rawAndroidResources } - assertNotNull(rawAndroidResources) - if (rawAndroidResources.isEmpty()) { - fail("rawAndroidResources is empty") - } - rawAndroidResources.forEach { - println(" - ${it.path}") - } - } - } -} - -class AllArtifactsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val allArtifacts = AGP.run { variant.allArtifacts } - assertNotNull(allArtifacts) - if (allArtifacts.isEmpty()) { - fail("allArtifacts is empty") - } - allArtifacts.forEach { (k, v) -> - println(" - $k => $v") - } - } - } -} - -class MinSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val minSdkVersion = AGP.run { variant.minSdkVersion } - assertNotNull(minSdkVersion) - assertEquals(MIN_SDK_VERSION, minSdkVersion.apiLevel) - } -} - -class TargetSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val targetSdkVersion = AGP.run { variant.targetSdkVersion } - assertNotNull(targetSdkVersion) - assertEquals(TARGET_SDK_VERSION, targetSdkVersion.apiLevel) - } -} - -class AarTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.library")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val aar = AGP.run { variant.aar }.search { - it.extension == "aar" - } - if (aar.isEmpty()) { - fail("aar is empty") - } - aar.forEach { - println(" - ${it.path}") - } - } - } -} - -class ApkTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val apk = AGP.run { variant.apk }.search { - it.extension == "apk" - } - if (apk.isEmpty()) { - fail("apk is empty") - } - apk.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedManifestsTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedManifests = AGP.run { variant.mergedManifests }.search { - it.name == "AndroidManifest.xml" - } - if (mergedManifests.isEmpty()) { - fail("mergedManifests is empty") - } - mergedManifests.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedResources = AGP.run { variant.mergedRes } - if (mergedResources.isEmpty()) { - fail("mergedRes is empty") - } - mergedResources.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedAssetsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedAssets = AGP.run { variant.mergedAssets } - if (mergedAssets.isEmpty()) { - fail("mergedAssets is empty") - } - mergedAssets.forEach { - println(" - ${it.path}") - } - } - } -} - -class ProcessedResTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val processedRes = AGP.run { variant.processedRes }.search { - it.extension == "ap_" - } - if (processedRes.isEmpty()) { - fail("processedRes is empty") - } - processedRes.forEach { - println(" - ${it.path}") - } - } - } -} - -class SymbolListTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val symbolList = AGP.run { variant.symbolList } - if (symbolList.isEmpty()) { - fail("symbolList is empty") - } - symbolList.forEach { - println(" - ${it.path}") - } - } - } -} - -class SymbolListWithPackageNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val symbolListWithPackageName = AGP.run { variant.symbolListWithPackageName } - if (symbolListWithPackageName.isEmpty()) { - fail("symbolListWithPackageName is empty") - } - symbolListWithPackageName.forEach { - println(" - ${it.path}") - } - } - } -} - -class AllClassesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val location = AGP.run { variant.allClasses }.files - assertTrue("ALL_CLASSES: $location", location::isNotEmpty) - assertTrue("No class file found at $location") { - location.search(File::isFile).isNotEmpty() - } - } - } -} - -class BuildToolsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val buildTools = AGP.run { variant.buildTools } - assertNotNull(buildTools) - BuildToolInfo.PathId.values().map { - it.name to buildTools.getPath(it) - }.forEach { (k, v) -> - println(" - $k => $v") - } - } -} diff --git a/booster-android-gradle-v4_2/src/integrationTest/resources/app.gradle b/booster-android-gradle-v4_2/src/integrationTest/resources/app.gradle deleted file mode 100644 index aa3c5f2d6..000000000 --- a/booster-android-gradle-v4_2/src/integrationTest/resources/app.gradle +++ /dev/null @@ -1,60 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } - dependencies { - classpath "com.android.tools.build:gradle:${project.android_gradle_version}" - classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { - exclude group: 'com.google.guava' - } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" - } -} - -apply plugin: 'com.android.application' -apply plugin: 'com.didiglobal.booster' -apply plugin: 'io.bootstage.testkit' - -android { - compileSdkVersion project.compile_sdk_version as Integer - buildToolsVersion project.build_tools_version - defaultConfig { - applicationId 'com.didiglobal.booster.test' - minSdkVersion project.min_sdk_version as Integer - targetSdkVersion project.target_sdk_version as Integer - versionCode 1 - versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - buildTypes { - debug { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - flavorDimensions 'lang' - productFlavors { - en { - dimension 'lang' - applicationIdSuffix '.en' - } - cn { - dimension 'lang' - applicationIdSuffix '.cn' - } - } - lintOptions { - checkReleaseBuilds false - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} diff --git a/booster-android-gradle-v4_2/src/integrationTest/resources/buildSrc/build.gradle b/booster-android-gradle-v4_2/src/integrationTest/resources/buildSrc/build.gradle deleted file mode 100644 index 79a9b104a..000000000 --- a/booster-android-gradle-v4_2/src/integrationTest/resources/buildSrc/build.gradle +++ /dev/null @@ -1,24 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} - -dependencies { - implementation "com.android.tools.build:gradle:${project.android_gradle_version}" - implementation("com.didiglobal.booster:booster-android-gradle-api:${project.booster_version}") { - exclude group: 'com.google.guava' - } - implementation "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" -} diff --git a/booster-android-gradle-v4_2/src/integrationTest/resources/lib.gradle b/booster-android-gradle-v4_2/src/integrationTest/resources/lib.gradle deleted file mode 100644 index adc9b1ca0..000000000 --- a/booster-android-gradle-v4_2/src/integrationTest/resources/lib.gradle +++ /dev/null @@ -1,57 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } - dependencies { - classpath "com.android.tools.build:gradle:${project.android_gradle_version}" - classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { - exclude group: 'com.google.guava' - } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" - } -} - -apply plugin: 'com.android.library' -apply plugin: 'com.didiglobal.booster' -apply plugin: 'io.bootstage.testkit' - -android { - compileSdkVersion project.compile_sdk_version as Integer - buildToolsVersion project.build_tools_version - defaultConfig { - minSdkVersion project.min_sdk_version as Integer - targetSdkVersion project.target_sdk_version as Integer - versionCode 1 - versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - buildTypes { - debug { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - flavorDimensions 'lang' - productFlavors { - en { - dimension 'lang' - } - cn { - dimension 'lang' - } - } - lintOptions { - checkReleaseBuilds false - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} diff --git a/booster-android-gradle-v4_2/src/integrationTest/resources/src/main/AndroidManifest.xml b/booster-android-gradle-v4_2/src/integrationTest/resources/src/main/AndroidManifest.xml deleted file mode 100644 index 30800c604..000000000 --- a/booster-android-gradle-v4_2/src/integrationTest/resources/src/main/AndroidManifest.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/booster-android-gradle-v4_2/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java b/booster-android-gradle-v4_2/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java deleted file mode 100644 index 0eb4ec7b4..000000000 --- a/booster-android-gradle-v4_2/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.didiglobal.booster.android.test; - -import android.app.Activity; - -public class MainActivity extends Activity { -} \ No newline at end of file diff --git a/booster-android-gradle-v4_2/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java b/booster-android-gradle-v4_2/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java deleted file mode 100644 index 3ecfb1507..000000000 --- a/booster-android-gradle-v4_2/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.didiglobal.booster.android.test; - -import android.app.Application; - -public class TestApplication extends Application { - -} \ No newline at end of file diff --git a/booster-android-gradle-v4_2/src/integrationTest/resources/src/main/res/values/strings.xml b/booster-android-gradle-v4_2/src/integrationTest/resources/src/main/res/values/strings.xml deleted file mode 100644 index 8b2247616..000000000 --- a/booster-android-gradle-v4_2/src/integrationTest/resources/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - Test - \ No newline at end of file diff --git a/booster-android-gradle-v4_2/src/main/kotlin/com/didiglobal/booster/android/gradle/v4_2/V42.kt b/booster-android-gradle-v4_2/src/main/kotlin/com/didiglobal/booster/android/gradle/v4_2/V42.kt deleted file mode 100644 index 1af49b16d..000000000 --- a/booster-android-gradle-v4_2/src/main/kotlin/com/didiglobal/booster/android/gradle/v4_2/V42.kt +++ /dev/null @@ -1,300 +0,0 @@ -package com.didiglobal.booster.android.gradle.v4_2 - -import com.android.build.api.artifact.Artifact -import com.android.build.api.artifact.ArtifactType -import com.android.build.api.artifact.MultipleArtifactType -import com.android.build.api.artifact.impl.ArtifactsImpl -import com.android.build.api.component.impl.ComponentImpl -import com.android.build.api.transform.Context -import com.android.build.api.transform.QualifiedContent -import com.android.build.gradle.api.ApplicationVariant -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.LibraryVariant -import com.android.build.gradle.internal.api.BaseVariantImpl -import com.android.build.gradle.internal.pipeline.TransformManager -import com.android.build.gradle.internal.pipeline.TransformTask -import com.android.build.gradle.internal.publishing.AndroidArtifacts -import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactScope -import com.android.build.gradle.internal.scope.AnchorOutputType -import com.android.build.gradle.internal.scope.GlobalScope -import com.android.build.gradle.internal.scope.InternalArtifactType -import com.android.build.gradle.internal.scope.InternalMultipleArtifactType -import com.android.build.gradle.internal.scope.VariantScope -import com.android.build.gradle.internal.variant.BaseVariantData -import com.android.builder.core.DefaultApiVersion -import com.android.builder.core.VariantType -import com.android.builder.model.ApiVersion -import com.android.sdklib.BuildToolInfo -import com.didiglobal.booster.gradle.AGPInterface -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.artifacts.ArtifactCollection -import org.gradle.api.artifacts.component.ComponentIdentifier -import org.gradle.api.artifacts.result.ResolvedArtifactResult -import org.gradle.api.artifacts.result.ResolvedDependencyResult -import org.gradle.api.file.FileCollection -import org.gradle.api.file.FileSystemLocation -import org.gradle.api.tasks.TaskProvider -import java.io.File -import java.util.TreeMap - -@Suppress("UnstableApiUsage") -private val SINGLE_ARTIFACT_TYPES = arrayOf( - ArtifactType::class, - AnchorOutputType::class, - InternalArtifactType::class -).map { - it.sealedSubclasses -}.flatten().map { - it.objectInstance as Artifact.SingleArtifact -}.associateBy { - it.javaClass.simpleName -} - -@Suppress("UnstableApiUsage") -private val MULTIPLE_ARTIFACT_TYPES = arrayOf( - MultipleArtifactType::class, - InternalMultipleArtifactType::class -).map { - it.sealedSubclasses -}.flatten().map { - it.objectInstance as Artifact.MultipleArtifact -}.associateBy { - it.javaClass.simpleName -} - -internal object V42 : AGPInterface { - - private val BaseVariant.component: ComponentImpl - get() = BaseVariantImpl::class.java.getDeclaredField("component").apply { - isAccessible = true - }.get(this) as ComponentImpl - - @Suppress("UnstableApiUsage") - private fun BaseVariant.getFinalArtifactFiles(type: Artifact.SingleArtifact): FileCollection { - return try { - project.objects.fileCollection().from(artifacts.get(type).get()) - } catch (e: Throwable) { - project.logger.warn(e.message, e) - project.objects.fileCollection().builtBy(artifacts.get(type)) - } - } - - @Suppress("UnstableApiUsage") - private fun BaseVariant.getFinalArtifactFiles(type: Artifact.MultipleArtifact): FileCollection { - return try { - project.objects.fileCollection().from(artifacts.getAll(type)) - } catch (e: Throwable) { - project.logger.warn(e.message, e) - project.objects.fileCollection().builtBy(artifacts.getAll(type)) - } - } - - @Suppress("UnstableApiUsage") - private val BaseVariant.artifacts: ArtifactsImpl - get() = component.artifacts - - override val scopeFullWithFeatures: MutableSet - get() = TransformManager.SCOPE_FULL_WITH_FEATURES - - override val scopeFullLibraryWithFeatures: MutableSet - get() = (TransformManager.SCOPE_FEATURES + QualifiedContent.Scope.PROJECT).toMutableSet() - - override val BaseVariant.project: Project - get() = globalScope.project - - override val BaseVariant.javaCompilerTaskProvider: TaskProvider - get() = javaCompileProvider - - override val BaseVariant.preBuildTaskProvider: TaskProvider - get() = preBuildProvider - - override val BaseVariant.assembleTaskProvider: TaskProvider - get() = assembleProvider - - override val BaseVariant.mergeAssetsTaskProvider: TaskProvider - get() = mergeAssetsProvider - - override val BaseVariant.mergeResourcesTaskProvider: TaskProvider - get() = try { - project.tasks.named(getTaskName("merge", "Resources")) - } catch (e: Throwable) { - mergeResourcesProvider - } - - override val BaseVariant.mergeNativeLibsTaskProvider: TaskProvider - get() = project.tasks.named(getTaskName("merge", "NativeLibs")) - - override val BaseVariant.processJavaResourcesTaskProvider: TaskProvider - get() = processJavaResourcesProvider - - override fun BaseVariant.getTaskName(prefix: String): String { - return component.computeTaskName(prefix) - } - - override fun BaseVariant.getTaskName(prefix: String, suffix: String): String { - return component.computeTaskName(prefix, suffix) - } - - override val BaseVariant.variantData: BaseVariantData - get() = javaClass.getDeclaredMethod("getVariantData").apply { - isAccessible = true - }.invoke(this) as BaseVariantData - - val BaseVariant.variantScope: VariantScope - get() = component.variantScope - - @Suppress("DEPRECATION") - private val BaseVariant.globalScope: GlobalScope - get() = component.globalScope - - override val BaseVariant.originalApplicationId: String - get() = component.variantDslInfo.packageName.get() - - override val BaseVariant.hasDynamicFeature: Boolean - get() = globalScope.hasDynamicFeatures() - - override val BaseVariant.rawAndroidResources: FileCollection - get() = component.variantData.allRawAndroidResources - - override val BaseVariant.localAndroidResources: FileCollection - get() = component.variantData.androidResources.values.reduce { collection, file -> - collection.plus(file) - } - - override fun BaseVariant.getArtifactCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): ArtifactCollection { - return component.variantDependencies.getArtifactCollection(configType, scope, artifactType) - } - - override fun BaseVariant.getArtifactFileCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): FileCollection { - return component.variantDependencies.getArtifactFileCollection(configType, scope, artifactType) - } - - override val BaseVariant.allArtifacts: Map - get() = TreeMap().also { all -> - SINGLE_ARTIFACT_TYPES.entries.associateTo(all) { (name, type) -> - val artifacts: FileCollection by lazy { - getFinalArtifactFiles(type) - } - name to artifacts - } - MULTIPLE_ARTIFACT_TYPES.entries.associateTo(all) { (name, type) -> - val artifacts: FileCollection by lazy { - getFinalArtifactFiles(type) - } - name to artifacts - } - } - - override val BaseVariant.minSdkVersion: ApiVersion - get() = DefaultApiVersion(component.minSdkVersion.apiLevel) - - override val BaseVariant.targetSdkVersion: ApiVersion - get() = component.targetSdkVersion - - private val BaseVariant.variantType: VariantType - get() = component.variantType - - override val BaseVariant.isApplication: Boolean - get() = variantType.isApk - - override val BaseVariant.isLibrary: Boolean - get() = variantType.isAar - - override val BaseVariant.isDynamicFeature: Boolean - get() = variantType.isDynamicFeature - - override val BaseVariant.aar: FileCollection - get() = getFinalArtifactFiles(ArtifactType.AAR) - - override val BaseVariant.apk: FileCollection - get() = getFinalArtifactFiles(ArtifactType.APK) - - override val BaseVariant.mergedManifests: FileCollection - get() = getFinalArtifactFiles(ArtifactType.MERGED_MANIFEST) - - override val BaseVariant.mergedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.MERGED_RES) - - override val BaseVariant.mergedNativeLibs: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.MERGED_NATIVE_LIBS) - - override val BaseVariant.mergedAssets: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.MERGED_ASSETS) - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.LIBRARY_ASSETS) - else -> TODO("Unsupported variant type: $variantType") - } - - override val BaseVariant.processedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.PROCESSED_RES) - - override val BaseVariant.symbolList: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.RUNTIME_SYMBOL_LIST) - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.COMPILE_SYMBOL_LIST) - else -> TODO("Unsupported variant type : $variantType") - } - - override val BaseVariant.symbolListWithPackageName: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.SYMBOL_LIST_WITH_PACKAGE_NAME) - - override val BaseVariant.dataBindingDependencyArtifacts: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.DATA_BINDING_DEPENDENCY_ARTIFACTS) - - override val BaseVariant.allClasses: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.JAVAC) + project.files("build${File.separator}tmp${File.separator}kotlin-classes${File.separator}${dirName}") - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.AAR_MAIN_JAR) - else -> project.files() - } - - override val BaseVariant.buildTools: BuildToolInfo - get() = globalScope.versionedSdkLoader.get().buildToolInfoProvider.get() - - override val BaseVariant.isPrecompileDependenciesResourcesEnabled: Boolean - get() = component.isPrecompileDependenciesResourcesEnabled - - override fun BaseVariant.getDependencies(transitive: Boolean, filter: (ComponentIdentifier) -> Boolean): Collection { - val all = getArtifactCollection( - AndroidArtifacts.ConsumedConfigType.RUNTIME_CLASSPATH, - AndroidArtifacts.ArtifactScope.ALL, - AndroidArtifacts.ArtifactType.CLASSES_JAR - ).filter { result -> - filter(result.id.componentIdentifier) - }.associateBy { - it.id.componentIdentifier.displayName - } - val result = if (!transitive) { - runtimeConfiguration.incoming.resolutionResult.root.dependencies.filterIsInstance().mapNotNull { - it.selected.id.displayName.takeIf { id -> id in all.keys } - }.associateWith { - all[it]!! - } - } else { - all - } - return result.values.toSet() - } - - override val Context.task: TransformTask - get() = javaClass.getDeclaredField("this$1").apply { - isAccessible = true - }.get(this).run { - javaClass.getDeclaredField("this$0").apply { - isAccessible = true - }.get(this) - } as TransformTask - - override val Project.aapt2Enabled: Boolean - get() = true - -} diff --git a/booster-android-gradle-v4_2/src/main/kotlin/com/didiglobal/booster/android/gradle/v4_2/V42Factory.kt b/booster-android-gradle-v4_2/src/main/kotlin/com/didiglobal/booster/android/gradle/v4_2/V42Factory.kt deleted file mode 100644 index e62782bf6..000000000 --- a/booster-android-gradle-v4_2/src/main/kotlin/com/didiglobal/booster/android/gradle/v4_2/V42Factory.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.didiglobal.booster.android.gradle.v4_2 - -import com.android.repository.Revision -import com.didiglobal.booster.gradle.AGPInterface -import com.didiglobal.booster.gradle.AGPInterfaceFactory -import com.google.auto.service.AutoService - -@AutoService(AGPInterfaceFactory::class) -class V42Factory : AGPInterfaceFactory { - - override val revision: Revision = Revision(4, 2, 0) - - override fun newAGPInterface(): AGPInterface = V42 - -} diff --git a/booster-android-gradle-v7_0/src/integrationTest/resources/app.gradle b/booster-android-gradle-v7_0/src/integrationTest/resources/app.gradle deleted file mode 100644 index aa3c5f2d6..000000000 --- a/booster-android-gradle-v7_0/src/integrationTest/resources/app.gradle +++ /dev/null @@ -1,60 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } - dependencies { - classpath "com.android.tools.build:gradle:${project.android_gradle_version}" - classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { - exclude group: 'com.google.guava' - } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" - } -} - -apply plugin: 'com.android.application' -apply plugin: 'com.didiglobal.booster' -apply plugin: 'io.bootstage.testkit' - -android { - compileSdkVersion project.compile_sdk_version as Integer - buildToolsVersion project.build_tools_version - defaultConfig { - applicationId 'com.didiglobal.booster.test' - minSdkVersion project.min_sdk_version as Integer - targetSdkVersion project.target_sdk_version as Integer - versionCode 1 - versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - buildTypes { - debug { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - flavorDimensions 'lang' - productFlavors { - en { - dimension 'lang' - applicationIdSuffix '.en' - } - cn { - dimension 'lang' - applicationIdSuffix '.cn' - } - } - lintOptions { - checkReleaseBuilds false - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} diff --git a/booster-android-gradle-v7_0/src/integrationTest/resources/buildSrc/build.gradle b/booster-android-gradle-v7_0/src/integrationTest/resources/buildSrc/build.gradle deleted file mode 100644 index 79a9b104a..000000000 --- a/booster-android-gradle-v7_0/src/integrationTest/resources/buildSrc/build.gradle +++ /dev/null @@ -1,24 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} - -dependencies { - implementation "com.android.tools.build:gradle:${project.android_gradle_version}" - implementation("com.didiglobal.booster:booster-android-gradle-api:${project.booster_version}") { - exclude group: 'com.google.guava' - } - implementation "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" -} diff --git a/booster-android-gradle-v7_0/src/integrationTest/resources/lib.gradle b/booster-android-gradle-v7_0/src/integrationTest/resources/lib.gradle deleted file mode 100644 index adc9b1ca0..000000000 --- a/booster-android-gradle-v7_0/src/integrationTest/resources/lib.gradle +++ /dev/null @@ -1,57 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } - dependencies { - classpath "com.android.tools.build:gradle:${project.android_gradle_version}" - classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { - exclude group: 'com.google.guava' - } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" - } -} - -apply plugin: 'com.android.library' -apply plugin: 'com.didiglobal.booster' -apply plugin: 'io.bootstage.testkit' - -android { - compileSdkVersion project.compile_sdk_version as Integer - buildToolsVersion project.build_tools_version - defaultConfig { - minSdkVersion project.min_sdk_version as Integer - targetSdkVersion project.target_sdk_version as Integer - versionCode 1 - versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - buildTypes { - debug { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - flavorDimensions 'lang' - productFlavors { - en { - dimension 'lang' - } - cn { - dimension 'lang' - } - } - lintOptions { - checkReleaseBuilds false - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} diff --git a/booster-android-gradle-v7_0/src/integrationTest/resources/src/main/AndroidManifest.xml b/booster-android-gradle-v7_0/src/integrationTest/resources/src/main/AndroidManifest.xml deleted file mode 100644 index 30800c604..000000000 --- a/booster-android-gradle-v7_0/src/integrationTest/resources/src/main/AndroidManifest.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/booster-android-gradle-v7_0/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java b/booster-android-gradle-v7_0/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java deleted file mode 100644 index 0eb4ec7b4..000000000 --- a/booster-android-gradle-v7_0/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.didiglobal.booster.android.test; - -import android.app.Activity; - -public class MainActivity extends Activity { -} \ No newline at end of file diff --git a/booster-android-gradle-v7_0/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java b/booster-android-gradle-v7_0/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java deleted file mode 100644 index 3ecfb1507..000000000 --- a/booster-android-gradle-v7_0/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.didiglobal.booster.android.test; - -import android.app.Application; - -public class TestApplication extends Application { - -} \ No newline at end of file diff --git a/booster-android-gradle-v7_0/src/integrationTest/resources/src/main/res/values/strings.xml b/booster-android-gradle-v7_0/src/integrationTest/resources/src/main/res/values/strings.xml deleted file mode 100644 index 8b2247616..000000000 --- a/booster-android-gradle-v7_0/src/integrationTest/resources/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - Test - \ No newline at end of file diff --git a/booster-android-gradle-v7_0/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_0/V70.kt b/booster-android-gradle-v7_0/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_0/V70.kt deleted file mode 100644 index 29e088279..000000000 --- a/booster-android-gradle-v7_0/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_0/V70.kt +++ /dev/null @@ -1,308 +0,0 @@ -package com.didiglobal.booster.android.gradle.v7_0 - -import com.android.build.api.artifact.Artifact -import com.android.build.api.artifact.MultipleArtifact -import com.android.build.api.artifact.SingleArtifact -import com.android.build.api.artifact.impl.ArtifactsImpl -import com.android.build.api.component.impl.ComponentImpl -import com.android.build.api.transform.Context -import com.android.build.api.transform.QualifiedContent -import com.android.build.gradle.api.ApplicationVariant -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.LibraryVariant -import com.android.build.gradle.internal.api.BaseVariantImpl -import com.android.build.gradle.internal.api.artifact.SourceArtifactType -import com.android.build.gradle.internal.pipeline.TransformManager -import com.android.build.gradle.internal.pipeline.TransformTask -import com.android.build.gradle.internal.publishing.AndroidArtifacts -import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactScope -import com.android.build.gradle.internal.scope.AnchorOutputType -import com.android.build.gradle.internal.scope.BuildArtifactType -import com.android.build.gradle.internal.scope.GlobalScope -import com.android.build.gradle.internal.scope.InternalArtifactType -import com.android.build.gradle.internal.scope.InternalMultipleArtifactType -import com.android.build.gradle.internal.scope.VariantScope -import com.android.build.gradle.internal.variant.BaseVariantData -import com.android.builder.core.DefaultApiVersion -import com.android.builder.core.VariantType -import com.android.builder.model.ApiVersion -import com.android.sdklib.BuildToolInfo -import com.didiglobal.booster.gradle.AGPInterface -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.artifacts.ArtifactCollection -import org.gradle.api.artifacts.component.ComponentIdentifier -import org.gradle.api.artifacts.result.ResolvedArtifactResult -import org.gradle.api.artifacts.result.ResolvedDependencyResult -import org.gradle.api.file.FileCollection -import org.gradle.api.file.FileSystemLocation -import org.gradle.api.tasks.TaskProvider -import java.io.File -import java.util.TreeMap - -@Suppress("UnstableApiUsage") -private val SINGLE_ARTIFACT_TYPES = arrayOf( - AnchorOutputType::class, - BuildArtifactType::class, - InternalArtifactType::class, - SingleArtifact::class, - SourceArtifactType::class -).map { - it.sealedSubclasses -}.flatten().map { - it.objectInstance as Artifact.Single -}.associateBy { - it.javaClass.simpleName -} - -private val MULTIPLE_ARTIFACT_TYPES = arrayOf( - MultipleArtifact::class, - InternalMultipleArtifactType::class -).map { - it.sealedSubclasses -}.flatten().map { - it.objectInstance as Artifact.Multiple -}.associateBy { - it.javaClass.simpleName -} - -@Suppress("DEPRECATION") -internal object V70 : AGPInterface { - - private val BaseVariant.component: ComponentImpl - get() = BaseVariantImpl::class.java.getDeclaredField("component").apply { - isAccessible = true - }.get(this) as ComponentImpl - - @Suppress("UnstableApiUsage") - private fun BaseVariant.getFinalArtifactFiles(type: Artifact.Single): FileCollection { - return try { - project.objects.fileCollection().from(artifacts.get(type)) - } catch (e: Throwable) { - project.logger.warn(e.message, e) - project.objects.fileCollection().builtBy(artifacts.get(type)) - } - } - - @Suppress("UnstableApiUsage") - private fun BaseVariant.getFinalArtifactFiles(type: Artifact.Multiple): FileCollection { - return try { - project.objects.fileCollection().from(artifacts.getAll(type)) - } catch (e: Throwable) { - project.logger.warn(e.message, e) - project.objects.fileCollection().builtBy(artifacts.getAll(type)) - } - } - - @Suppress("UnstableApiUsage") - private val BaseVariant.artifacts: ArtifactsImpl - get() = component.artifacts - - override val scopeFullWithFeatures: MutableSet - get() = TransformManager.SCOPE_FULL_WITH_FEATURES - - override val scopeFullLibraryWithFeatures: MutableSet - get() = (TransformManager.SCOPE_FEATURES + QualifiedContent.Scope.PROJECT).toMutableSet() - - override val BaseVariant.project: Project - get() = globalScope.run { - javaClass.getDeclaredField("project").apply { - isAccessible = true - }.get(this) as Project - } - - override val BaseVariant.javaCompilerTaskProvider: TaskProvider - get() = javaCompileProvider - - override val BaseVariant.preBuildTaskProvider: TaskProvider - get() = preBuildProvider - - override val BaseVariant.assembleTaskProvider: TaskProvider - get() = assembleProvider - - override val BaseVariant.mergeAssetsTaskProvider: TaskProvider - get() = mergeAssetsProvider - - override val BaseVariant.mergeResourcesTaskProvider: TaskProvider - get() = try { - project.tasks.named(getTaskName("merge", "Resources")) - } catch (e: Throwable) { - mergeResourcesProvider - } - - override val BaseVariant.mergeNativeLibsTaskProvider: TaskProvider - get() = project.tasks.named(getTaskName("merge", "NativeLibs")) - - override val BaseVariant.processJavaResourcesTaskProvider: TaskProvider - get() = processJavaResourcesProvider - - override fun BaseVariant.getTaskName(prefix: String): String { - return component.computeTaskName(prefix) - } - - override fun BaseVariant.getTaskName(prefix: String, suffix: String): String { - return component.computeTaskName(prefix, suffix) - } - - override val BaseVariant.variantData: BaseVariantData - get() = javaClass.getDeclaredMethod("getVariantData").apply { - isAccessible = true - }.invoke(this) as BaseVariantData - - val BaseVariant.variantScope: VariantScope - get() = component.variantScope - - @Suppress("DEPRECATION") - private val BaseVariant.globalScope: GlobalScope - get() = component.globalScope - - override val BaseVariant.originalApplicationId: String - get() = component.variantDslInfo.namespace.get() - - override val BaseVariant.hasDynamicFeature: Boolean - get() = globalScope.hasDynamicFeatures() - - override val BaseVariant.rawAndroidResources: FileCollection - get() = component.variantData.allRawAndroidResources - - override val BaseVariant.localAndroidResources: FileCollection - get() = component.variantData.androidResources.values.reduce { collection, file -> - collection.plus(file) - } - - override fun BaseVariant.getArtifactCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): ArtifactCollection { - return component.variantDependencies.getArtifactCollection(configType, scope, artifactType) - } - - override fun BaseVariant.getArtifactFileCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): FileCollection { - return component.variantDependencies.getArtifactFileCollection(configType, scope, artifactType) - } - - override val BaseVariant.allArtifacts: Map - get() = TreeMap().also { all -> - SINGLE_ARTIFACT_TYPES.entries.associateTo(all) { (name, type) -> - val artifacts: FileCollection by lazy { - getFinalArtifactFiles(type) - } - name to artifacts - } - MULTIPLE_ARTIFACT_TYPES.entries.associateTo(all) { (name, type) -> - val artifacts: FileCollection by lazy { - getFinalArtifactFiles(type) - } - name to artifacts - } - } - - override val BaseVariant.minSdkVersion: ApiVersion - get() = DefaultApiVersion(component.minSdkVersion.apiLevel) - - override val BaseVariant.targetSdkVersion: ApiVersion - get() = component.variantDslInfo.targetSdkVersion - - private val BaseVariant.variantType: VariantType - get() = component.variantType - - override val BaseVariant.isApplication: Boolean - get() = variantType.isApk - - override val BaseVariant.isLibrary: Boolean - get() = variantType.isAar - - override val BaseVariant.isDynamicFeature: Boolean - get() = variantType.isDynamicFeature - - override val BaseVariant.aar: FileCollection - get() = getFinalArtifactFiles(SingleArtifact.AAR) - - override val BaseVariant.apk: FileCollection - get() = getFinalArtifactFiles(SingleArtifact.APK) - - override val BaseVariant.mergedManifests: FileCollection - get() = getFinalArtifactFiles(SingleArtifact.MERGED_MANIFEST) - - override val BaseVariant.mergedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.MERGED_RES) - - override val BaseVariant.mergedNativeLibs: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.MERGED_NATIVE_LIBS) - - override val BaseVariant.mergedAssets: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.MERGED_ASSETS) - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.LIBRARY_ASSETS) - else -> TODO("Unsupported variant type: $variantType") - } - - override val BaseVariant.processedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.PROCESSED_RES) - - override val BaseVariant.symbolList: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.RUNTIME_SYMBOL_LIST) - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.COMPILE_SYMBOL_LIST) - else -> TODO("Unsupported variant type : $variantType") - } - - override val BaseVariant.symbolListWithPackageName: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.SYMBOL_LIST_WITH_PACKAGE_NAME) - - override val BaseVariant.dataBindingDependencyArtifacts: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.DATA_BINDING_DEPENDENCY_ARTIFACTS) - - override val BaseVariant.allClasses: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.JAVAC) + project.files("build${File.separator}tmp${File.separator}kotlin-classes${File.separator}${dirName}") - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.AAR_MAIN_JAR) - else -> project.files() - } - - override val BaseVariant.buildTools: BuildToolInfo - get() = globalScope.versionedSdkLoader.get().buildToolInfoProvider.get() - - override val BaseVariant.isPrecompileDependenciesResourcesEnabled: Boolean - get() = component.isPrecompileDependenciesResourcesEnabled - - override fun BaseVariant.getDependencies(transitive: Boolean, filter: (ComponentIdentifier) -> Boolean): Collection { - val all = getArtifactCollection( - AndroidArtifacts.ConsumedConfigType.RUNTIME_CLASSPATH, - AndroidArtifacts.ArtifactScope.ALL, - AndroidArtifacts.ArtifactType.CLASSES_JAR - ).filter { result -> - filter(result.id.componentIdentifier) - }.associateBy { - it.id.componentIdentifier.displayName - } - val result = if (!transitive) { - runtimeConfiguration.incoming.resolutionResult.root.dependencies.filterIsInstance().mapNotNull { - it.selected.id.displayName.takeIf { id -> id in all.keys } - }.associateWith { - all[it]!! - } - } else { - all - } - return result.values.toSet() - } - - override val Context.task: TransformTask - get() = javaClass.getDeclaredField("this$1").apply { - isAccessible = true - }.get(this).run { - javaClass.getDeclaredField("this$0").apply { - isAccessible = true - }.get(this) - } as TransformTask - - override val Project.aapt2Enabled: Boolean - get() = true - -} diff --git a/booster-android-gradle-v7_0/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_0/V70Factory.kt b/booster-android-gradle-v7_0/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_0/V70Factory.kt deleted file mode 100644 index 2d91acecc..000000000 --- a/booster-android-gradle-v7_0/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_0/V70Factory.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.didiglobal.booster.android.gradle.v7_0 - -import com.android.repository.Revision -import com.didiglobal.booster.gradle.AGPInterface -import com.didiglobal.booster.gradle.AGPInterfaceFactory -import com.google.auto.service.AutoService - -@AutoService(AGPInterfaceFactory::class) -class V70Factory : AGPInterfaceFactory { - - override val revision: Revision = Revision(7, 0, 0) - - override fun newAGPInterface(): AGPInterface = V70 - -} diff --git a/booster-android-gradle-v7_1/src/integrationTest/resources/app.gradle b/booster-android-gradle-v7_1/src/integrationTest/resources/app.gradle deleted file mode 100644 index aa3c5f2d6..000000000 --- a/booster-android-gradle-v7_1/src/integrationTest/resources/app.gradle +++ /dev/null @@ -1,60 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } - dependencies { - classpath "com.android.tools.build:gradle:${project.android_gradle_version}" - classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { - exclude group: 'com.google.guava' - } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" - } -} - -apply plugin: 'com.android.application' -apply plugin: 'com.didiglobal.booster' -apply plugin: 'io.bootstage.testkit' - -android { - compileSdkVersion project.compile_sdk_version as Integer - buildToolsVersion project.build_tools_version - defaultConfig { - applicationId 'com.didiglobal.booster.test' - minSdkVersion project.min_sdk_version as Integer - targetSdkVersion project.target_sdk_version as Integer - versionCode 1 - versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - buildTypes { - debug { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - flavorDimensions 'lang' - productFlavors { - en { - dimension 'lang' - applicationIdSuffix '.en' - } - cn { - dimension 'lang' - applicationIdSuffix '.cn' - } - } - lintOptions { - checkReleaseBuilds false - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} diff --git a/booster-android-gradle-v7_1/src/integrationTest/resources/buildSrc/build.gradle b/booster-android-gradle-v7_1/src/integrationTest/resources/buildSrc/build.gradle deleted file mode 100644 index 79a9b104a..000000000 --- a/booster-android-gradle-v7_1/src/integrationTest/resources/buildSrc/build.gradle +++ /dev/null @@ -1,24 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} - -dependencies { - implementation "com.android.tools.build:gradle:${project.android_gradle_version}" - implementation("com.didiglobal.booster:booster-android-gradle-api:${project.booster_version}") { - exclude group: 'com.google.guava' - } - implementation "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" -} diff --git a/booster-android-gradle-v7_1/src/integrationTest/resources/lib.gradle b/booster-android-gradle-v7_1/src/integrationTest/resources/lib.gradle deleted file mode 100644 index adc9b1ca0..000000000 --- a/booster-android-gradle-v7_1/src/integrationTest/resources/lib.gradle +++ /dev/null @@ -1,57 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } - dependencies { - classpath "com.android.tools.build:gradle:${project.android_gradle_version}" - classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { - exclude group: 'com.google.guava' - } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" - } -} - -apply plugin: 'com.android.library' -apply plugin: 'com.didiglobal.booster' -apply plugin: 'io.bootstage.testkit' - -android { - compileSdkVersion project.compile_sdk_version as Integer - buildToolsVersion project.build_tools_version - defaultConfig { - minSdkVersion project.min_sdk_version as Integer - targetSdkVersion project.target_sdk_version as Integer - versionCode 1 - versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - buildTypes { - debug { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - flavorDimensions 'lang' - productFlavors { - en { - dimension 'lang' - } - cn { - dimension 'lang' - } - } - lintOptions { - checkReleaseBuilds false - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} diff --git a/booster-android-gradle-v7_1/src/integrationTest/resources/src/main/AndroidManifest.xml b/booster-android-gradle-v7_1/src/integrationTest/resources/src/main/AndroidManifest.xml deleted file mode 100644 index 30800c604..000000000 --- a/booster-android-gradle-v7_1/src/integrationTest/resources/src/main/AndroidManifest.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/booster-android-gradle-v7_1/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java b/booster-android-gradle-v7_1/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java deleted file mode 100644 index 0eb4ec7b4..000000000 --- a/booster-android-gradle-v7_1/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.didiglobal.booster.android.test; - -import android.app.Activity; - -public class MainActivity extends Activity { -} \ No newline at end of file diff --git a/booster-android-gradle-v7_1/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java b/booster-android-gradle-v7_1/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java deleted file mode 100644 index 3ecfb1507..000000000 --- a/booster-android-gradle-v7_1/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.didiglobal.booster.android.test; - -import android.app.Application; - -public class TestApplication extends Application { - -} \ No newline at end of file diff --git a/booster-android-gradle-v7_1/src/integrationTest/resources/src/main/res/values/strings.xml b/booster-android-gradle-v7_1/src/integrationTest/resources/src/main/res/values/strings.xml deleted file mode 100644 index 8b2247616..000000000 --- a/booster-android-gradle-v7_1/src/integrationTest/resources/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - Test - \ No newline at end of file diff --git a/booster-android-gradle-v7_1/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_1/V71.kt b/booster-android-gradle-v7_1/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_1/V71.kt deleted file mode 100644 index 772453781..000000000 --- a/booster-android-gradle-v7_1/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_1/V71.kt +++ /dev/null @@ -1,304 +0,0 @@ -package com.didiglobal.booster.android.gradle.v7_1 - -import com.android.build.api.artifact.Artifact -import com.android.build.api.artifact.MultipleArtifact -import com.android.build.api.artifact.SingleArtifact -import com.android.build.api.artifact.impl.ArtifactsImpl -import com.android.build.api.component.impl.ComponentImpl -import com.android.build.api.transform.Context -import com.android.build.api.transform.QualifiedContent -import com.android.build.gradle.api.ApplicationVariant -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.LibraryVariant -import com.android.build.gradle.internal.api.BaseVariantImpl -import com.android.build.gradle.internal.api.artifact.SourceArtifactType -import com.android.build.gradle.internal.pipeline.TransformManager -import com.android.build.gradle.internal.pipeline.TransformTask -import com.android.build.gradle.internal.publishing.AndroidArtifacts -import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactScope -import com.android.build.gradle.internal.scope.BuildArtifactType -import com.android.build.gradle.internal.scope.GlobalScope -import com.android.build.gradle.internal.scope.InternalArtifactType -import com.android.build.gradle.internal.scope.InternalMultipleArtifactType -import com.android.build.gradle.internal.scope.VariantScope -import com.android.build.gradle.internal.variant.BaseVariantData -import com.android.builder.core.DefaultApiVersion -import com.android.builder.core.VariantType -import com.android.builder.model.ApiVersion -import com.android.sdklib.BuildToolInfo -import com.didiglobal.booster.gradle.AGPInterface -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.artifacts.ArtifactCollection -import org.gradle.api.artifacts.component.ComponentIdentifier -import org.gradle.api.artifacts.result.ResolvedArtifactResult -import org.gradle.api.artifacts.result.ResolvedDependencyResult -import org.gradle.api.file.FileCollection -import org.gradle.api.file.FileSystemLocation -import org.gradle.api.tasks.TaskProvider -import java.io.File -import java.util.TreeMap - -@Suppress("UnstableApiUsage") -private val SINGLE_ARTIFACT_TYPES = arrayOf( - BuildArtifactType::class, - InternalArtifactType::class, - SingleArtifact::class, - SourceArtifactType::class -).map { - it.sealedSubclasses -}.flatten().map { - it.objectInstance as Artifact.Single -}.associateBy { - it.javaClass.simpleName -} - -private val MULTIPLE_ARTIFACT_TYPES = arrayOf( - MultipleArtifact::class, - InternalMultipleArtifactType::class -).map { - it.sealedSubclasses -}.flatten().map { - it.objectInstance as Artifact.Multiple -}.associateBy { - it.javaClass.simpleName -} - -@Suppress("DEPRECATION") -internal object V71 : AGPInterface { - - private val BaseVariant.component: ComponentImpl - get() = BaseVariantImpl::class.java.getDeclaredField("component").apply { - isAccessible = true - }.get(this) as ComponentImpl - - @Suppress("UnstableApiUsage") - private fun BaseVariant.getFinalArtifactFiles(type: Artifact.Single): FileCollection { - return try { - project.objects.fileCollection().from(artifacts.get(type)) - } catch (e: Throwable) { - project.objects.fileCollection().builtBy(artifacts.get(type)) - } - } - - @Suppress("UnstableApiUsage") - private fun BaseVariant.getFinalArtifactFiles(type: Artifact.Multiple): FileCollection { - return try { - project.objects.fileCollection().from(artifacts.getAll(type)) - } catch (e: Throwable) { - project.objects.fileCollection().builtBy(artifacts.getAll(type)) - } - } - - @Suppress("UnstableApiUsage") - private val BaseVariant.artifacts: ArtifactsImpl - get() = component.artifacts - - override val scopeFullWithFeatures: MutableSet - get() = TransformManager.SCOPE_FULL_WITH_FEATURES - - override val scopeFullLibraryWithFeatures: MutableSet - get() = (TransformManager.SCOPE_FEATURES + QualifiedContent.Scope.PROJECT).toMutableSet() - - override val BaseVariant.project: Project - get() = globalScope.run { - javaClass.getDeclaredField("project").apply { - isAccessible = true - }.get(this) as Project - } - - override val BaseVariant.javaCompilerTaskProvider: TaskProvider - get() = javaCompileProvider - - override val BaseVariant.preBuildTaskProvider: TaskProvider - get() = preBuildProvider - - override val BaseVariant.assembleTaskProvider: TaskProvider - get() = assembleProvider - - override val BaseVariant.mergeAssetsTaskProvider: TaskProvider - get() = mergeAssetsProvider - - override val BaseVariant.mergeResourcesTaskProvider: TaskProvider - get() = try { - project.tasks.named(getTaskName("merge", "Resources")) - } catch (e: Throwable) { - mergeResourcesProvider - } - - override val BaseVariant.mergeNativeLibsTaskProvider: TaskProvider - get() = project.tasks.named(getTaskName("merge", "NativeLibs")) - - override val BaseVariant.processJavaResourcesTaskProvider: TaskProvider - get() = processJavaResourcesProvider - - override fun BaseVariant.getTaskName(prefix: String): String { - return component.computeTaskName(prefix) - } - - override fun BaseVariant.getTaskName(prefix: String, suffix: String): String { - return component.computeTaskName(prefix, suffix) - } - - override val BaseVariant.variantData: BaseVariantData - get() = javaClass.getDeclaredMethod("getVariantData").apply { - isAccessible = true - }.invoke(this) as BaseVariantData - - val BaseVariant.variantScope: VariantScope - get() = component.variantScope - - @Suppress("DEPRECATION") - private val BaseVariant.globalScope: GlobalScope - get() = component.globalScope - - override val BaseVariant.originalApplicationId: String - get() = component.variantDslInfo.namespace.get() - - override val BaseVariant.hasDynamicFeature: Boolean - get() = globalScope.hasDynamicFeatures() - - override val BaseVariant.rawAndroidResources: FileCollection - get() = component.variantData.allRawAndroidResources - - override val BaseVariant.localAndroidResources: FileCollection - get() = component.variantData.androidResources.values.reduce { collection, file -> - collection.plus(file) - } - - override fun BaseVariant.getArtifactCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): ArtifactCollection { - return component.variantDependencies.getArtifactCollection(configType, scope, artifactType) - } - - override fun BaseVariant.getArtifactFileCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): FileCollection { - return component.variantDependencies.getArtifactFileCollection(configType, scope, artifactType) - } - - override val BaseVariant.allArtifacts: Map - get() = TreeMap().also { all -> - SINGLE_ARTIFACT_TYPES.entries.associateTo(all) { (name, type) -> - val artifacts: FileCollection by lazy { - getFinalArtifactFiles(type) - } - name to artifacts - } - MULTIPLE_ARTIFACT_TYPES.entries.associateTo(all) { (name, type) -> - val artifacts: FileCollection by lazy { - getFinalArtifactFiles(type) - } - name to artifacts - } - } - - override val BaseVariant.minSdkVersion: ApiVersion - get() = DefaultApiVersion(component.minSdkVersion.apiLevel) - - override val BaseVariant.targetSdkVersion: ApiVersion - get() = DefaultApiVersion(component.targetSdkVersion.apiLevel) - - private val BaseVariant.variantType: VariantType - get() = component.variantType - - override val BaseVariant.isApplication: Boolean - get() = variantType.isApk - - override val BaseVariant.isLibrary: Boolean - get() = variantType.isAar - - override val BaseVariant.isDynamicFeature: Boolean - get() = variantType.isDynamicFeature - - override val BaseVariant.aar: FileCollection - get() = getFinalArtifactFiles(SingleArtifact.AAR) - - override val BaseVariant.apk: FileCollection - get() = getFinalArtifactFiles(SingleArtifact.APK) - - override val BaseVariant.mergedManifests: FileCollection - get() = getFinalArtifactFiles(SingleArtifact.MERGED_MANIFEST) - - override val BaseVariant.mergedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.MERGED_RES) - - override val BaseVariant.mergedNativeLibs: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.MERGED_NATIVE_LIBS) - - override val BaseVariant.mergedAssets: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.COMPRESSED_ASSETS) - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.LIBRARY_ASSETS) - else -> TODO("Unsupported variant type: $variantType") - } - - override val BaseVariant.processedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.PROCESSED_RES) - - override val BaseVariant.symbolList: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.RUNTIME_SYMBOL_LIST) - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.COMPILE_SYMBOL_LIST) - else -> TODO("Unsupported variant type : $variantType") - } - - override val BaseVariant.symbolListWithPackageName: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.SYMBOL_LIST_WITH_PACKAGE_NAME) - - override val BaseVariant.dataBindingDependencyArtifacts: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.DATA_BINDING_DEPENDENCY_ARTIFACTS) - - override val BaseVariant.allClasses: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.JAVAC) + project.files("build${File.separator}tmp${File.separator}kotlin-classes${File.separator}${dirName}") - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.AAR_MAIN_JAR) - else -> project.files() - } - - override val BaseVariant.buildTools: BuildToolInfo - get() = globalScope.versionedSdkLoader.get().buildToolInfoProvider.get() - - override val BaseVariant.isPrecompileDependenciesResourcesEnabled: Boolean - get() = component.isPrecompileDependenciesResourcesEnabled - - override fun BaseVariant.getDependencies(transitive: Boolean, filter: (ComponentIdentifier) -> Boolean): Collection { - val all = getArtifactCollection( - AndroidArtifacts.ConsumedConfigType.RUNTIME_CLASSPATH, - AndroidArtifacts.ArtifactScope.ALL, - AndroidArtifacts.ArtifactType.CLASSES_JAR - ).filter { result -> - filter(result.id.componentIdentifier) - }.associateBy { - it.id.componentIdentifier.displayName - } - val result = if (!transitive) { - runtimeConfiguration.incoming.resolutionResult.root.dependencies.filterIsInstance().mapNotNull { - it.selected.id.displayName.takeIf { id -> id in all.keys } - }.associateWith { - all[it]!! - } - } else { - all - } - return result.values.toSet() - } - - override val Context.task: TransformTask - get() = javaClass.getDeclaredField("this$1").apply { - isAccessible = true - }.get(this).run { - javaClass.getDeclaredField("this$0").apply { - isAccessible = true - }.get(this) - } as TransformTask - - override val Project.aapt2Enabled: Boolean - get() = true - -} diff --git a/booster-android-gradle-v7_1/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_1/V71Factory.kt b/booster-android-gradle-v7_1/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_1/V71Factory.kt deleted file mode 100644 index 64d4a7d90..000000000 --- a/booster-android-gradle-v7_1/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_1/V71Factory.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.didiglobal.booster.android.gradle.v7_1 - -import com.android.repository.Revision -import com.didiglobal.booster.gradle.AGPInterface -import com.didiglobal.booster.gradle.AGPInterfaceFactory -import com.google.auto.service.AutoService - -@AutoService(AGPInterfaceFactory::class) -class V71Factory : AGPInterfaceFactory { - - override val revision: Revision = Revision(7, 1, 0) - - override fun newAGPInterface(): AGPInterface = V71 - -} diff --git a/booster-android-gradle-v7_2/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v7_2/V72IntegrationTest.kt b/booster-android-gradle-v7_2/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v7_2/V72IntegrationTest.kt deleted file mode 100644 index 4d2c89ce2..000000000 --- a/booster-android-gradle-v7_2/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v7_2/V72IntegrationTest.kt +++ /dev/null @@ -1,478 +0,0 @@ -@file:Suppress("DEPRECATION") - -package com.didiglobal.booster.android.gradle.v7_2 - -import com.android.build.gradle.AppExtension -import com.android.build.gradle.BaseExtension -import com.android.build.gradle.LibraryExtension -import com.android.build.gradle.api.BaseVariant -import com.didiglobal.booster.gradle.AGP -import com.didiglobal.booster.gradle.getAndroid -import com.didiglobal.booster.kotlinx.search -import io.bootstage.testkit.gradle.Case -import io.bootstage.testkit.gradle.TestCase -import io.bootstage.testkit.gradle.VariantTestCase -import io.bootstage.testkit.gradle.rules.GradleExecutor -import io.bootstage.testkit.gradle.rules.LocalProperties -import io.bootstage.testkit.gradle.rules.copyFromResource -import io.bootstage.testkit.gradle.rules.rule -import org.gradle.api.Project -import org.junit.Before -import org.junit.Rule -import org.junit.rules.TemporaryFolder -import org.junit.rules.TestRule -import java.io.File -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertNotNull -import kotlin.test.assertTrue -import kotlin.test.fail - -private val MIN_SDK_VERSION = System.getProperty("android.minsdk.version").toInt() - -private const val TARGET_SDK_VERSION = 30 - -private val ARGS = System.getProperty("gradle.args").split("\\s+".toRegex()) + listOf( - "-Pbooster_version=${Build.VERSION}", - "-Pandroid_gradle_version=7.2.0", - "-Pcompile_sdk_version=30", - "-Pbuild_tools_version=29.0.2", - "-Pmin_sdk_version=${MIN_SDK_VERSION}", - "-Ptarget_sdk_version=${TARGET_SDK_VERSION}" -) - -@Suppress("RemoveCurlyBracesFromTemplate", "FunctionName") -abstract class V72IntegrationTest(private val isLib: Boolean) { - - private val projectDir = TemporaryFolder() - - @get:Rule - val ruleChain: TestRule = rule(projectDir) { - rule(LocalProperties(projectDir::getRoot)) { - GradleExecutor(projectDir::getRoot, "7.3.3", *ARGS.toTypedArray()) - } - } - - @Before - fun setup() { - projectDir.copyFromResource("${if (isLib) "lib" else "app"}.gradle", "build.gradle") - projectDir.copyFromResource("buildSrc") - projectDir.copyFromResource("src") - projectDir.newFile("gradle.properties").writeText("org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=2g") - assertEquals(7, AGP.revision.major) - assertEquals(2, AGP.revision.minor) - } - - @Test - @Case(ScopeFullWithFeaturesTest::class) - fun `test AGPInterface#scopeFullWithFeatures`() = Unit - - @Test - @Case(ScopeFullLibraryWithFeaturesTest::class) - fun `test AGPInterface#scopeFullLibraryWithFeatures`() = Unit - - @Test - @Case(ProjectTest::class) - fun `test AGPInterface#project`() = Unit - - @Test - @Case(JavaCompilerTaskTestUnit::class) - fun `test AGPInterface#javaCompilerTask`() = Unit - - @Test - @Case(PreBuildTaskTestUnit::class) - fun `test AGPInterface#preBuildTask`() = Unit - - @Test - @Case(AssembleTaskTestUnit::class) - fun `test AGPInterface#assembleTask`() = Unit - - @Test - @Case(MergeAssetsTaskTestUnit::class) - fun `test AGPInterface#mergeAssetsTask`() = Unit - - @Test - @Case(MergeResourcesTaskTestUnit::class) - fun `test AGPInterface#mergeResources`() = Unit - - @Test - @Case(GetTaskNameTestUnit::class) - fun `test AGPInterface#getTaskName(String)`() = Unit - - @Test - @Case(GetTaskName2TestUnit::class) - fun `test AGPInterface#getTaskName(String, String)`() = Unit - - @Test - @Case(VariantDataTestUnit::class) - fun `test AGPInterface#variantData`() = Unit - - @Test - @Case(OriginalApplicationIdTestUnit::class) - fun `test AGPInterface#originalApplicationId`() = Unit - - @Test - @Case(HasDynamicFeatureTestUnit::class) - fun `test AGPInterface#hasDynamicFeature`() = Unit - - @Test - @Case(RawAndroidResourcesTestUnit::class) - fun `test AGPInterface#rawAndroidResources`() = Unit - - @Test - @Case(AllArtifactsTestUnit::class) - fun `test AGPInterface#allArtifacts`() = Unit - - @Test - @Case(MinSdkVersionTestUnit::class) - fun `test AGPInterface#minSdkVersion`() = Unit - - @Test - @Case(TargetSdkVersionTestUnit::class) - fun `test AGPInterface#targetSdkVersion`() = Unit - - @Test - @Case(AarTestUnit::class) - fun `test AGPInterface#aar`() { - } - - @Test - @Case(ApkTestUnit::class) - fun `test AGPInterface#apk`() { - } - - @Test - @Case(MergedManifestsTestUnit::class) - fun `test AGPInterface#mergedManifests`() { - } - - @Test - @Case(MergedResourcesTestUnit::class) - fun `test AGPInterface#mergedRes`() { - } - - @Test - @Case(MergedAssetsTestUnit::class) - fun `test AGPInterface#mergedAssets`() { - } - - @Test - @Case(ProcessedResTestUnit::class) - fun `test AGPInterface#processedRes`() { - } - - @Test - @Case(SymbolListTestUnit::class) - fun `test AGPInterface#symbolList`() { - } - - @Test - @Case(SymbolListWithPackageNameTestUnit::class) - fun `test AGPInterface#symbolListWithPackageName`() { - } - - @Test - @Case(AllClassesTestUnit::class) - fun `test AGPInterface#allClasses`() { - } - -// @Test -// @Case(BuildToolsTestUnit::class) -// fun `test AGPInterface#buildTools`() { -// } - -} - -class V72AppIntegrationTest : V72IntegrationTest(false) - -class V72LibIntegrationTest : V72IntegrationTest(true) - -class ScopeFullWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("PROJECT,SUB_PROJECTS,EXTERNAL_LIBRARIES,FEATURES", AGP.scopeFullWithFeatures.joinToString(",")) - } -} - -class ScopeFullLibraryWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("FEATURES,PROJECT", AGP.scopeFullLibraryWithFeatures.joinToString(",")) - } -} - -class ProjectTest : TestCase { - override fun apply(project: Project) { - val assert: (BaseVariant) -> Unit = { variant -> - assertEquals(project, AGP.run { variant.project }) - } - project.afterEvaluate { - when (val android = project.getAndroid()) { - is AppExtension -> android.applicationVariants.forEach(assert) - is LibraryExtension -> android.libraryVariants.forEach(assert) - } - } - } -} - -class JavaCompilerTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.javaCompilerTask }) - } -} - -class PreBuildTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.preBuildTask }) - } -} - -class AssembleTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.assembleTask }) - } -} - -class MergeAssetsTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeAssetsTask }) - } -} - -class MergeResourcesTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeResourcesTask }) - } -} - -class GetTaskNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("assemble${variant.name.capitalize()}", AGP.run { variant.getTaskName("assemble") }) - } -} - - -class GetTaskName2TestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("merge${variant.name.capitalize()}Resources", AGP.run { variant.getTaskName("merge", "Resources") }) - } -} - -class VariantDataTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.variantData }) - } -} - -class OriginalApplicationIdTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.originalApplicationId }) - } -} - -class HasDynamicFeatureTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertFalse(AGP.run { variant.hasDynamicFeature }) - } -} - -class RawAndroidResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val rawAndroidResources = AGP.run { variant.rawAndroidResources } - assertNotNull(rawAndroidResources) - if (rawAndroidResources.isEmpty()) { - fail("rawAndroidResources is empty") - } - rawAndroidResources.forEach { - println(" - ${it.path}") - } - } - } -} - -class AllArtifactsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val allArtifacts = AGP.run { variant.allArtifacts } - assertNotNull(allArtifacts) - if (allArtifacts.isEmpty()) { - fail("allArtifacts is empty") - } - allArtifacts.forEach { (k, v) -> - println(" - $k => $v") - } - } - } -} - -class MinSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val minSdkVersion = AGP.run { variant.minSdkVersion } - assertNotNull(minSdkVersion) - assertEquals(MIN_SDK_VERSION, minSdkVersion.apiLevel) - } -} - -class TargetSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val targetSdkVersion = AGP.run { variant.targetSdkVersion } - assertNotNull(targetSdkVersion) - assertEquals(TARGET_SDK_VERSION, targetSdkVersion.apiLevel) - } -} - -class AarTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.library")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val aar = AGP.run { variant.aar }.search { - it.extension == "aar" - } - if (aar.isEmpty()) { - fail("aar is empty") - } - aar.forEach { - println(" - ${it.path}") - } - } - } -} - -class ApkTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val apk = AGP.run { variant.apk }.search { - it.extension == "apk" - } - if (apk.isEmpty()) { - fail("apk is empty") - } - apk.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedManifestsTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedManifests = AGP.run { variant.mergedManifests }.search { - it.name == "AndroidManifest.xml" - } - if (mergedManifests.isEmpty()) { - fail("mergedManifests is empty") - } - mergedManifests.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedResources = AGP.run { variant.mergedRes } - if (mergedResources.isEmpty()) { - fail("mergedRes is empty") - } - mergedResources.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedAssetsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedAssets = AGP.run { variant.mergedAssets } - if (mergedAssets.isEmpty()) { - fail("mergedAssets is empty") - } - mergedAssets.forEach { - println(" - ${it.path}") - } - } - } -} - -class ProcessedResTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val processedRes = AGP.run { variant.processedRes }.search { - it.extension == "ap_" - } - if (processedRes.isEmpty()) { - fail("processedRes is empty") - } - processedRes.forEach { - println(" - ${it.path}") - } - } - } -} - -class SymbolListTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val symbolList = AGP.run { variant.symbolList } - if (symbolList.isEmpty()) { - fail("symbolList is empty") - } - symbolList.forEach { - println(" - ${it.path}") - } - } - } -} - -class SymbolListWithPackageNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val symbolListWithPackageName = AGP.run { variant.symbolListWithPackageName } - if (symbolListWithPackageName.isEmpty()) { - fail("symbolListWithPackageName is empty") - } - symbolListWithPackageName.forEach { - println(" - ${it.path}") - } - } - } -} - -class AllClassesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val location = AGP.run { variant.allClasses }.files - assertTrue("ALL_CLASSES: $location", location::isNotEmpty) - assertTrue("No class file found at $location") { - location.search(File::isFile).isNotEmpty() - } - } - } -} diff --git a/booster-android-gradle-v7_2/src/integrationTest/resources/app.gradle b/booster-android-gradle-v7_2/src/integrationTest/resources/app.gradle deleted file mode 100644 index aa3c5f2d6..000000000 --- a/booster-android-gradle-v7_2/src/integrationTest/resources/app.gradle +++ /dev/null @@ -1,60 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } - dependencies { - classpath "com.android.tools.build:gradle:${project.android_gradle_version}" - classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { - exclude group: 'com.google.guava' - } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" - } -} - -apply plugin: 'com.android.application' -apply plugin: 'com.didiglobal.booster' -apply plugin: 'io.bootstage.testkit' - -android { - compileSdkVersion project.compile_sdk_version as Integer - buildToolsVersion project.build_tools_version - defaultConfig { - applicationId 'com.didiglobal.booster.test' - minSdkVersion project.min_sdk_version as Integer - targetSdkVersion project.target_sdk_version as Integer - versionCode 1 - versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - buildTypes { - debug { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - flavorDimensions 'lang' - productFlavors { - en { - dimension 'lang' - applicationIdSuffix '.en' - } - cn { - dimension 'lang' - applicationIdSuffix '.cn' - } - } - lintOptions { - checkReleaseBuilds false - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} diff --git a/booster-android-gradle-v7_2/src/integrationTest/resources/buildSrc/build.gradle b/booster-android-gradle-v7_2/src/integrationTest/resources/buildSrc/build.gradle deleted file mode 100644 index 79a9b104a..000000000 --- a/booster-android-gradle-v7_2/src/integrationTest/resources/buildSrc/build.gradle +++ /dev/null @@ -1,24 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} - -dependencies { - implementation "com.android.tools.build:gradle:${project.android_gradle_version}" - implementation("com.didiglobal.booster:booster-android-gradle-api:${project.booster_version}") { - exclude group: 'com.google.guava' - } - implementation "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" -} diff --git a/booster-android-gradle-v7_2/src/integrationTest/resources/lib.gradle b/booster-android-gradle-v7_2/src/integrationTest/resources/lib.gradle deleted file mode 100644 index adc9b1ca0..000000000 --- a/booster-android-gradle-v7_2/src/integrationTest/resources/lib.gradle +++ /dev/null @@ -1,57 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } - dependencies { - classpath "com.android.tools.build:gradle:${project.android_gradle_version}" - classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { - exclude group: 'com.google.guava' - } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" - } -} - -apply plugin: 'com.android.library' -apply plugin: 'com.didiglobal.booster' -apply plugin: 'io.bootstage.testkit' - -android { - compileSdkVersion project.compile_sdk_version as Integer - buildToolsVersion project.build_tools_version - defaultConfig { - minSdkVersion project.min_sdk_version as Integer - targetSdkVersion project.target_sdk_version as Integer - versionCode 1 - versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - buildTypes { - debug { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - flavorDimensions 'lang' - productFlavors { - en { - dimension 'lang' - } - cn { - dimension 'lang' - } - } - lintOptions { - checkReleaseBuilds false - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} diff --git a/booster-android-gradle-v7_2/src/integrationTest/resources/src/main/AndroidManifest.xml b/booster-android-gradle-v7_2/src/integrationTest/resources/src/main/AndroidManifest.xml deleted file mode 100644 index 30800c604..000000000 --- a/booster-android-gradle-v7_2/src/integrationTest/resources/src/main/AndroidManifest.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/booster-android-gradle-v7_2/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java b/booster-android-gradle-v7_2/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java deleted file mode 100644 index 0eb4ec7b4..000000000 --- a/booster-android-gradle-v7_2/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.didiglobal.booster.android.test; - -import android.app.Activity; - -public class MainActivity extends Activity { -} \ No newline at end of file diff --git a/booster-android-gradle-v7_2/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java b/booster-android-gradle-v7_2/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java deleted file mode 100644 index 3ecfb1507..000000000 --- a/booster-android-gradle-v7_2/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.didiglobal.booster.android.test; - -import android.app.Application; - -public class TestApplication extends Application { - -} \ No newline at end of file diff --git a/booster-android-gradle-v7_2/src/integrationTest/resources/src/main/res/values/strings.xml b/booster-android-gradle-v7_2/src/integrationTest/resources/src/main/res/values/strings.xml deleted file mode 100644 index 8b2247616..000000000 --- a/booster-android-gradle-v7_2/src/integrationTest/resources/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - Test - \ No newline at end of file diff --git a/booster-android-gradle-v7_2/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_2/V72.kt b/booster-android-gradle-v7_2/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_2/V72.kt deleted file mode 100644 index f561fc468..000000000 --- a/booster-android-gradle-v7_2/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_2/V72.kt +++ /dev/null @@ -1,314 +0,0 @@ -package com.didiglobal.booster.android.gradle.v7_2 - -import com.android.build.api.artifact.Artifact -import com.android.build.api.artifact.MultipleArtifact -import com.android.build.api.artifact.SingleArtifact -import com.android.build.api.artifact.impl.ArtifactsImpl -import com.android.build.api.component.impl.ComponentImpl -import com.android.build.api.transform.Context -import com.android.build.api.transform.QualifiedContent -import com.android.build.gradle.api.ApplicationVariant -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.LibraryVariant -import com.android.build.gradle.internal.api.BaseVariantImpl -import com.android.build.gradle.internal.api.artifact.SourceArtifactType -import com.android.build.gradle.internal.pipeline.TransformManager -import com.android.build.gradle.internal.pipeline.TransformTask -import com.android.build.gradle.internal.publishing.AndroidArtifacts -import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactScope -import com.android.build.gradle.internal.scope.BuildArtifactType -import com.android.build.gradle.internal.scope.InternalArtifactType -import com.android.build.gradle.internal.scope.InternalMultipleArtifactType -import com.android.build.gradle.internal.scope.VariantScope -import com.android.build.gradle.internal.tasks.factory.GlobalTaskCreationConfigImpl -import com.android.build.gradle.internal.variant.BaseVariantData -import com.android.builder.core.DefaultApiVersion -import com.android.builder.core.VariantType -import com.android.builder.model.ApiVersion -import com.android.sdklib.BuildToolInfo -import com.didiglobal.booster.gradle.AGPInterface -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.artifacts.ArtifactCollection -import org.gradle.api.artifacts.component.ComponentIdentifier -import org.gradle.api.artifacts.result.ResolvedArtifactResult -import org.gradle.api.artifacts.result.ResolvedDependencyResult -import org.gradle.api.file.FileCollection -import org.gradle.api.file.FileSystemLocation -import org.gradle.api.tasks.TaskProvider -import java.io.File -import java.util.TreeMap - -@Suppress("UnstableApiUsage") -private val SINGLE_ARTIFACT_TYPES = arrayOf( - BuildArtifactType::class, - InternalArtifactType::class, - SingleArtifact::class, - SourceArtifactType::class -).map { - it.sealedSubclasses -}.flatten().map { - it.objectInstance as Artifact.Single -}.associateBy { - it.javaClass.simpleName -} - -private val MULTIPLE_ARTIFACT_TYPES = arrayOf( - MultipleArtifact::class, - InternalMultipleArtifactType::class -).map { - it.sealedSubclasses -}.flatten().map { - it.objectInstance as Artifact.Multiple -}.associateBy { - it.javaClass.simpleName -} - -@Suppress("DEPRECATION") -internal object V72 : AGPInterface { - - private val BaseVariant.component: ComponentImpl - get() = BaseVariantImpl::class.java.getDeclaredField("component").apply { - isAccessible = true - }.get(this) as ComponentImpl - - @Suppress("UnstableApiUsage") - private fun BaseVariant.getFinalArtifactFiles(type: Artifact.Single): FileCollection { - return try { - project.objects.fileCollection().from(artifacts.get(type)) - } catch (e: Throwable) { - project.objects.fileCollection().builtBy(artifacts.get(type)) - } - } - - @Suppress("UnstableApiUsage") - private fun BaseVariant.getFinalArtifactFiles(type: Artifact.Multiple): FileCollection { - return try { - project.objects.fileCollection().from(artifacts.getAll(type)) - } catch (e: Throwable) { - project.objects.fileCollection().builtBy(artifacts.getAll(type)) - } - } - - private inline fun Sequence.firstOfOrNull(transform: (T) -> R?): R? { - for (element in this) { - val result = transform(element) - if (result != null) { - return result - } - } - return null - } - - @Suppress("UnstableApiUsage") - private val BaseVariant.artifacts: ArtifactsImpl - get() = component.artifacts - - override val scopeFullWithFeatures: MutableSet - get() = TransformManager.SCOPE_FULL_WITH_FEATURES - - override val scopeFullLibraryWithFeatures: MutableSet - get() = (TransformManager.SCOPE_FEATURES + QualifiedContent.Scope.PROJECT).toMutableSet() - - override val BaseVariant.project: Project - get() = component.variantDependencies.run { - javaClass.getDeclaredField("project").apply { - isAccessible = true - }.get(this) as Project - } - - override val BaseVariant.javaCompilerTaskProvider: TaskProvider - get() = javaCompileProvider - - override val BaseVariant.preBuildTaskProvider: TaskProvider - get() = preBuildProvider - - override val BaseVariant.assembleTaskProvider: TaskProvider - get() = assembleProvider - - override val BaseVariant.mergeAssetsTaskProvider: TaskProvider - get() = mergeAssetsProvider - - override val BaseVariant.mergeResourcesTaskProvider: TaskProvider - get() = try { - project.tasks.named(getTaskName("merge", "Resources")) - } catch (e: Throwable) { - mergeResourcesProvider - } - - override val BaseVariant.mergeNativeLibsTaskProvider: TaskProvider - get() = project.tasks.named(getTaskName("merge", "NativeLibs")) - - override val BaseVariant.processJavaResourcesTaskProvider: TaskProvider - get() = processJavaResourcesProvider - - override fun BaseVariant.getTaskName(prefix: String): String { - return component.computeTaskName(prefix) - } - - override fun BaseVariant.getTaskName(prefix: String, suffix: String): String { - return component.computeTaskName(prefix, suffix) - } - - override val BaseVariant.variantData: BaseVariantData - get() = javaClass.getDeclaredMethod("getVariantData").apply { - isAccessible = true - }.invoke(this) as BaseVariantData - - val BaseVariant.variantScope: VariantScope - get() = component.variantScope - - @Suppress("DEPRECATION") - private val BaseVariant.globalScope: GlobalTaskCreationConfigImpl - get() = component.global as GlobalTaskCreationConfigImpl - - override val BaseVariant.originalApplicationId: String - get() = component.variantDslInfo.namespace.get() - - override val BaseVariant.hasDynamicFeature: Boolean - get() = globalScope.hasDynamicFeatures - - override val BaseVariant.rawAndroidResources: FileCollection - get() = component.variantData.allRawAndroidResources - - override val BaseVariant.localAndroidResources: FileCollection - get() = component.variantData.androidResources.values.reduce { collection, file -> - collection.plus(file) - } - - override fun BaseVariant.getArtifactCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): ArtifactCollection { - return component.variantDependencies.getArtifactCollection(configType, scope, artifactType) - } - - override fun BaseVariant.getArtifactFileCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): FileCollection { - return component.variantDependencies.getArtifactFileCollection(configType, scope, artifactType) - } - - override val BaseVariant.allArtifacts: Map - get() = TreeMap().also { all -> - SINGLE_ARTIFACT_TYPES.entries.associateTo(all) { (name, type) -> - val artifacts: FileCollection by lazy { - getFinalArtifactFiles(type) - } - name to artifacts - } - MULTIPLE_ARTIFACT_TYPES.entries.associateTo(all) { (name, type) -> - val artifacts: FileCollection by lazy { - getFinalArtifactFiles(type) - } - name to artifacts - } - } - - override val BaseVariant.minSdkVersion: ApiVersion - get() = DefaultApiVersion(component.minSdkVersion.apiLevel) - - override val BaseVariant.targetSdkVersion: ApiVersion - get() = DefaultApiVersion(component.targetSdkVersion.apiLevel) - - private val BaseVariant.variantType: VariantType - get() = component.variantType - - override val BaseVariant.isApplication: Boolean - get() = variantType.isApk - - override val BaseVariant.isLibrary: Boolean - get() = variantType.isAar - - override val BaseVariant.isDynamicFeature: Boolean - get() = variantType.isDynamicFeature - - override val BaseVariant.aar: FileCollection - get() = getFinalArtifactFiles(SingleArtifact.AAR) - - override val BaseVariant.apk: FileCollection - get() = getFinalArtifactFiles(SingleArtifact.APK) - - override val BaseVariant.mergedManifests: FileCollection - get() = getFinalArtifactFiles(SingleArtifact.MERGED_MANIFEST) - - override val BaseVariant.mergedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.MERGED_RES) - - override val BaseVariant.mergedNativeLibs: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.MERGED_NATIVE_LIBS) - - override val BaseVariant.mergedAssets: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.COMPRESSED_ASSETS) - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.LIBRARY_ASSETS) - else -> TODO("Unsupported variant type: $variantType") - } - - override val BaseVariant.processedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.PROCESSED_RES) - - override val BaseVariant.symbolList: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.RUNTIME_SYMBOL_LIST) - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.COMPILE_SYMBOL_LIST) - else -> TODO("Unsupported variant type : $variantType") - } - - override val BaseVariant.symbolListWithPackageName: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.SYMBOL_LIST_WITH_PACKAGE_NAME) - - override val BaseVariant.dataBindingDependencyArtifacts: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.DATA_BINDING_DEPENDENCY_ARTIFACTS) - - override val BaseVariant.allClasses: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.JAVAC) + project.files("build${File.separator}tmp${File.separator}kotlin-classes${File.separator}${dirName}") - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.AAR_MAIN_JAR) - else -> project.files() - } - - override val BaseVariant.buildTools: BuildToolInfo - get() = globalScope.versionedSdkLoader.get().buildToolInfoProvider.get() - - override val BaseVariant.isPrecompileDependenciesResourcesEnabled: Boolean - get() = component.isPrecompileDependenciesResourcesEnabled - - override fun BaseVariant.getDependencies(transitive: Boolean, filter: (ComponentIdentifier) -> Boolean): Collection { - val all = getArtifactCollection( - AndroidArtifacts.ConsumedConfigType.RUNTIME_CLASSPATH, - AndroidArtifacts.ArtifactScope.ALL, - AndroidArtifacts.ArtifactType.CLASSES_JAR - ).filter { result -> - filter(result.id.componentIdentifier) - }.associateBy { - it.id.componentIdentifier.displayName - } - val result = if (!transitive) { - runtimeConfiguration.incoming.resolutionResult.root.dependencies.filterIsInstance().mapNotNull { - it.selected.id.displayName.takeIf { id -> id in all.keys } - }.associateWith { - all[it]!! - } - } else { - all - } - return result.values.toSet() - } - - override val Context.task: TransformTask - get() = javaClass.getDeclaredField("this$1").apply { - isAccessible = true - }.get(this).run { - javaClass.getDeclaredField("this$0").apply { - isAccessible = true - }.get(this) - } as TransformTask - - override val Project.aapt2Enabled: Boolean - get() = true - -} diff --git a/booster-android-gradle-v7_2/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_2/V72Factory.kt b/booster-android-gradle-v7_2/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_2/V72Factory.kt deleted file mode 100644 index ed10da597..000000000 --- a/booster-android-gradle-v7_2/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_2/V72Factory.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.didiglobal.booster.android.gradle.v7_2 - -import com.android.repository.Revision -import com.didiglobal.booster.gradle.AGPInterface -import com.didiglobal.booster.gradle.AGPInterfaceFactory -import com.google.auto.service.AutoService - -@AutoService(AGPInterfaceFactory::class) -class V72Factory : AGPInterfaceFactory { - - override val revision: Revision = Revision(7, 2, 0) - - override fun newAGPInterface(): AGPInterface = V72 - -} diff --git a/booster-android-gradle-v7_3/README.md b/booster-android-gradle-v7_3/README.md deleted file mode 100644 index a5e9fa76e..000000000 --- a/booster-android-gradle-v7_3/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# booster-android-gradle-v7_3 - -This module is an implementation of [booster-android-gradle-api](../booster-android-gradle-api) for Android gradle plugin above 7.3 - -本模块是 [booster-android-gradle-api](../booster-android-gradle-api) 针对 Android gradle plugin 7.3 以上版本的实现。 - diff --git a/booster-android-gradle-v7_3/build.gradle b/booster-android-gradle-v7_3/build.gradle deleted file mode 100644 index 93e585e70..000000000 --- a/booster-android-gradle-v7_3/build.gradle +++ /dev/null @@ -1,27 +0,0 @@ -apply plugin: 'java-gradle-plugin' - -apply from: "$rootDir/gradle/booster.gradle" -apply from: "$rootDir/gradle/integration-test.gradle" -apply from: "$rootDir/gradle/functional-test.gradle" - -dependencies { - kapt 'com.google.auto.service:auto-service:1.0' - api 'com.google.auto.service:auto-service:1.0' - api project(':booster-android-gradle-compat') - compileOnly 'com.android.tools:repository:30.0.0' - compileOnly 'com.android.tools:common:30.0.0' - compileOnly 'com.android.tools:sdklib:30.0.0' - compileOnly 'com.android.tools.build:gradle:7.3.0' - testImplementation 'com.android.tools.build:gradle:7.3.0' - testImplementation 'com.android.tools:common:30.0.0' - testImplementation 'io.bootstage.testkit:testkit-gradle-plugin:1.1.0' - testImplementation project(':booster-build') -} - -jar { - exclude('com/android/sdklib/BuildToolInfo.class') -} - -gradlePlugin { - testSourceSets sourceSets.functionalTest, sourceSets.integrationTest -} \ No newline at end of file diff --git a/booster-android-gradle-v7_3/src/integrationTest/resources/app.gradle b/booster-android-gradle-v7_3/src/integrationTest/resources/app.gradle deleted file mode 100644 index aa3c5f2d6..000000000 --- a/booster-android-gradle-v7_3/src/integrationTest/resources/app.gradle +++ /dev/null @@ -1,60 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } - dependencies { - classpath "com.android.tools.build:gradle:${project.android_gradle_version}" - classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { - exclude group: 'com.google.guava' - } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" - } -} - -apply plugin: 'com.android.application' -apply plugin: 'com.didiglobal.booster' -apply plugin: 'io.bootstage.testkit' - -android { - compileSdkVersion project.compile_sdk_version as Integer - buildToolsVersion project.build_tools_version - defaultConfig { - applicationId 'com.didiglobal.booster.test' - minSdkVersion project.min_sdk_version as Integer - targetSdkVersion project.target_sdk_version as Integer - versionCode 1 - versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - buildTypes { - debug { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - flavorDimensions 'lang' - productFlavors { - en { - dimension 'lang' - applicationIdSuffix '.en' - } - cn { - dimension 'lang' - applicationIdSuffix '.cn' - } - } - lintOptions { - checkReleaseBuilds false - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} diff --git a/booster-android-gradle-v7_3/src/integrationTest/resources/buildSrc/build.gradle b/booster-android-gradle-v7_3/src/integrationTest/resources/buildSrc/build.gradle deleted file mode 100644 index 79a9b104a..000000000 --- a/booster-android-gradle-v7_3/src/integrationTest/resources/buildSrc/build.gradle +++ /dev/null @@ -1,24 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} - -dependencies { - implementation "com.android.tools.build:gradle:${project.android_gradle_version}" - implementation("com.didiglobal.booster:booster-android-gradle-api:${project.booster_version}") { - exclude group: 'com.google.guava' - } - implementation "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" -} diff --git a/booster-android-gradle-v7_3/src/integrationTest/resources/lib.gradle b/booster-android-gradle-v7_3/src/integrationTest/resources/lib.gradle deleted file mode 100644 index adc9b1ca0..000000000 --- a/booster-android-gradle-v7_3/src/integrationTest/resources/lib.gradle +++ /dev/null @@ -1,57 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } - dependencies { - classpath "com.android.tools.build:gradle:${project.android_gradle_version}" - classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { - exclude group: 'com.google.guava' - } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" - } -} - -apply plugin: 'com.android.library' -apply plugin: 'com.didiglobal.booster' -apply plugin: 'io.bootstage.testkit' - -android { - compileSdkVersion project.compile_sdk_version as Integer - buildToolsVersion project.build_tools_version - defaultConfig { - minSdkVersion project.min_sdk_version as Integer - targetSdkVersion project.target_sdk_version as Integer - versionCode 1 - versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - buildTypes { - debug { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - flavorDimensions 'lang' - productFlavors { - en { - dimension 'lang' - } - cn { - dimension 'lang' - } - } - lintOptions { - checkReleaseBuilds false - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} diff --git a/booster-android-gradle-v7_3/src/integrationTest/resources/src/main/AndroidManifest.xml b/booster-android-gradle-v7_3/src/integrationTest/resources/src/main/AndroidManifest.xml deleted file mode 100644 index 30800c604..000000000 --- a/booster-android-gradle-v7_3/src/integrationTest/resources/src/main/AndroidManifest.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/booster-android-gradle-v7_3/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java b/booster-android-gradle-v7_3/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java deleted file mode 100644 index 0eb4ec7b4..000000000 --- a/booster-android-gradle-v7_3/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.didiglobal.booster.android.test; - -import android.app.Activity; - -public class MainActivity extends Activity { -} \ No newline at end of file diff --git a/booster-android-gradle-v7_3/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java b/booster-android-gradle-v7_3/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java deleted file mode 100644 index 3ecfb1507..000000000 --- a/booster-android-gradle-v7_3/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.didiglobal.booster.android.test; - -import android.app.Application; - -public class TestApplication extends Application { - -} \ No newline at end of file diff --git a/booster-android-gradle-v7_3/src/integrationTest/resources/src/main/res/values/strings.xml b/booster-android-gradle-v7_3/src/integrationTest/resources/src/main/res/values/strings.xml deleted file mode 100644 index 8b2247616..000000000 --- a/booster-android-gradle-v7_3/src/integrationTest/resources/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - Test - \ No newline at end of file diff --git a/booster-android-gradle-v7_3/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_3/V73.kt b/booster-android-gradle-v7_3/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_3/V73.kt deleted file mode 100644 index cef70d2f9..000000000 --- a/booster-android-gradle-v7_3/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_3/V73.kt +++ /dev/null @@ -1,328 +0,0 @@ -package com.didiglobal.booster.android.gradle.v7_3 - -import com.android.build.api.artifact.Artifact -import com.android.build.api.artifact.MultipleArtifact -import com.android.build.api.artifact.SingleArtifact -import com.android.build.api.artifact.impl.ArtifactsImpl -import com.android.build.api.component.impl.ComponentImpl -import com.android.build.api.transform.Context -import com.android.build.api.transform.QualifiedContent -import com.android.build.gradle.api.ApplicationVariant -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.LibraryVariant -import com.android.build.gradle.internal.api.BaseVariantImpl -import com.android.build.gradle.internal.api.artifact.SourceArtifactType -import com.android.build.gradle.internal.pipeline.TransformManager -import com.android.build.gradle.internal.pipeline.TransformTask -import com.android.build.gradle.internal.publishing.AndroidArtifacts -import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactScope -import com.android.build.gradle.internal.scope.BuildArtifactType -import com.android.build.gradle.internal.scope.InternalArtifactType -import com.android.build.gradle.internal.scope.InternalMultipleArtifactType -import com.android.build.gradle.internal.scope.VariantScope -import com.android.build.gradle.internal.tasks.factory.GlobalTaskCreationConfigImpl -import com.android.build.gradle.internal.variant.BaseVariantData -import com.android.builder.core.DefaultApiVersion -import com.android.builder.model.ApiVersion -import com.android.sdklib.BuildToolInfo -import com.didiglobal.booster.gradle.AGPInterface -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.artifacts.ArtifactCollection -import org.gradle.api.artifacts.component.ComponentIdentifier -import org.gradle.api.artifacts.result.ResolvedArtifactResult -import org.gradle.api.artifacts.result.ResolvedDependencyResult -import org.gradle.api.file.ConfigurableFileCollection -import org.gradle.api.file.FileCollection -import org.gradle.api.file.FileSystemLocation -import org.gradle.api.tasks.TaskProvider -import java.io.File -import java.util.TreeMap - -@Suppress("UnstableApiUsage") -private val SINGLE_ARTIFACT_TYPES = arrayOf( - BuildArtifactType::class, - InternalArtifactType::class, - SingleArtifact::class, - SourceArtifactType::class -).map { - it.sealedSubclasses -}.flatten().map { - it.objectInstance as Artifact.Single -}.associateBy { - it.javaClass.simpleName -} - -private val MULTIPLE_ARTIFACT_TYPES = arrayOf( - MultipleArtifact::class, - InternalMultipleArtifactType::class -).map { - it.sealedSubclasses -}.flatten().map { - it.objectInstance as Artifact.Multiple -}.associateBy { - it.javaClass.simpleName -} - -@Suppress("DEPRECATION") -internal object V73 : AGPInterface { - - private val BaseVariant.component: ComponentImpl - get() = BaseVariantImpl::class.java.getDeclaredField("component").apply { - isAccessible = true - }.get(this) as ComponentImpl - - @Suppress("UnstableApiUsage") - private fun BaseVariant.getFinalArtifactFiles(type: Artifact.Single): FileCollection { - return try { - project.objects.fileCollection().from(artifacts.get(type)) - } catch (e: Throwable) { - project.objects.fileCollection().builtBy(artifacts.get(type)) - } - } - - @Suppress("UnstableApiUsage") - private fun BaseVariant.getFinalArtifactFiles(type: Artifact.Multiple): FileCollection { - return try { - project.objects.fileCollection().from(artifacts.getAll(type)) - } catch (e: Throwable) { - project.objects.fileCollection().builtBy(artifacts.getAll(type)) - } - } - - @Suppress("UnstableApiUsage") - private val BaseVariant.artifacts: ArtifactsImpl - get() = component.artifacts - - override val scopeFullWithFeatures: MutableSet - get() = TransformManager.SCOPE_FULL_WITH_FEATURES - - override val scopeFullLibraryWithFeatures: MutableSet - get() = (TransformManager.SCOPE_FEATURES + QualifiedContent.Scope.PROJECT).toMutableSet() - - override val BaseVariant.project: Project - get() = component.variantDependencies.run { - javaClass.getDeclaredField("project").apply { - isAccessible = true - }.get(this) as Project - } - - override val BaseVariant.javaCompilerTaskProvider: TaskProvider - get() = javaCompileProvider - - override val BaseVariant.preBuildTaskProvider: TaskProvider - get() = preBuildProvider - - override val BaseVariant.assembleTaskProvider: TaskProvider - get() = assembleProvider - - override val BaseVariant.mergeAssetsTaskProvider: TaskProvider - get() = mergeAssetsProvider - - override val BaseVariant.mergeResourcesTaskProvider: TaskProvider - get() = try { - project.tasks.named(getTaskName("merge", "Resources")) - } catch (e: Throwable) { - mergeResourcesProvider - } - - override val BaseVariant.mergeNativeLibsTaskProvider: TaskProvider - get() = project.tasks.named(getTaskName("merge", "NativeLibs")) - - override val BaseVariant.processJavaResourcesTaskProvider: TaskProvider - get() = processJavaResourcesProvider - - override fun BaseVariant.getTaskName(prefix: String): String { - return component.computeTaskName(prefix) - } - - override fun BaseVariant.getTaskName(prefix: String, suffix: String): String { - return component.computeTaskName(prefix, suffix) - } - - override val BaseVariant.variantData: BaseVariantData - get() = javaClass.getDeclaredMethod("getVariantData").apply { - isAccessible = true - }.invoke(this) as BaseVariantData - - val BaseVariant.variantScope: VariantScope - get() = component.variantScope - - @Suppress("DEPRECATION") - private val BaseVariant.globalScope: GlobalTaskCreationConfigImpl - get() = component.global as GlobalTaskCreationConfigImpl - - override val BaseVariant.originalApplicationId: String - get() = component.namespace.get() - - override val BaseVariant.hasDynamicFeature: Boolean - get() = component.global.hasDynamicFeatures - - override val BaseVariant.rawAndroidResources: FileCollection - get() { - val allRes: ConfigurableFileCollection = component.services.fileCollection() - - allRes.from(component.variantDependencies.getArtifactCollection( - AndroidArtifacts.ConsumedConfigType.RUNTIME_CLASSPATH, - ArtifactScope.ALL, - AndroidArtifacts.ArtifactType.ANDROID_RES - ).artifactFiles) - - allRes.from(component.services.fileCollection(variantData.extraGeneratedResFolders) - .builtBy(listOfNotNull(variantData.extraGeneratedResFolders.builtBy))) - - component.taskContainer.generateApkDataTask?.let { - allRes.from(artifacts.get(InternalArtifactType.MICRO_APK_RES)) - } - - allRes.from(component.sources.res.getVariantSources().map { allSources -> - allSources.map { directoryEntries -> - directoryEntries.directoryEntries.map { - it.asFiles(component.services::directoryProperty) - } - } - }) - - return allRes - } - - override val BaseVariant.localAndroidResources: FileCollection - get() = component.services.fileCollection().from(component.sources.res.getLocalSourcesAsFileCollection().map { - it.values.reduce { acc, files -> - acc.plus(files) - } - }) - - override fun BaseVariant.getArtifactCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): ArtifactCollection { - return component.variantDependencies.getArtifactCollection(configType, scope, artifactType) - } - - override fun BaseVariant.getArtifactFileCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): FileCollection { - return component.variantDependencies.getArtifactFileCollection(configType, scope, artifactType) - } - - override val BaseVariant.allArtifacts: Map - get() = TreeMap().also { all -> - SINGLE_ARTIFACT_TYPES.entries.associateTo(all) { (name, type) -> - val artifacts: FileCollection by lazy { - getFinalArtifactFiles(type) - } - name to artifacts - } - MULTIPLE_ARTIFACT_TYPES.entries.associateTo(all) { (name, type) -> - val artifacts: FileCollection by lazy { - getFinalArtifactFiles(type) - } - name to artifacts - } - } - - override val BaseVariant.minSdkVersion: ApiVersion - get() = DefaultApiVersion(component.minSdkVersion.apiLevel) - - override val BaseVariant.targetSdkVersion: ApiVersion - get() = DefaultApiVersion(component.targetSdkVersion.apiLevel) - - override val BaseVariant.isApplication: Boolean - get() = component.componentType.isApk - - override val BaseVariant.isLibrary: Boolean - get() = component.componentType.isAar - - override val BaseVariant.isDynamicFeature: Boolean - get() = component.componentType.isDynamicFeature - - override val BaseVariant.aar: FileCollection - get() = getFinalArtifactFiles(SingleArtifact.AAR) - - override val BaseVariant.apk: FileCollection - get() = getFinalArtifactFiles(SingleArtifact.APK) - - override val BaseVariant.mergedManifests: FileCollection - get() = getFinalArtifactFiles(SingleArtifact.MERGED_MANIFEST) - - override val BaseVariant.mergedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.MERGED_RES) - - override val BaseVariant.mergedNativeLibs: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.MERGED_NATIVE_LIBS) - - override val BaseVariant.mergedAssets: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.COMPRESSED_ASSETS) - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.LIBRARY_ASSETS) - else -> TODO("Unsupported variant type: $name") - } - - override val BaseVariant.processedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.PROCESSED_RES) - - override val BaseVariant.symbolList: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.RUNTIME_SYMBOL_LIST) - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.COMPILE_SYMBOL_LIST) - else -> TODO("Unsupported variant type : $name") - } - - override val BaseVariant.symbolListWithPackageName: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.SYMBOL_LIST_WITH_PACKAGE_NAME) - - override val BaseVariant.dataBindingDependencyArtifacts: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.DATA_BINDING_DEPENDENCY_ARTIFACTS) - - override val BaseVariant.allClasses: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.JAVAC) + project.files("build${File.separator}tmp${File.separator}kotlin-classes${File.separator}${dirName}") - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.AAR_MAIN_JAR) - else -> project.files() - } - - override val BaseVariant.buildTools: BuildToolInfo - get() = globalScope.versionedSdkLoader.get().buildToolInfoProvider.get() - - override val BaseVariant.isPrecompileDependenciesResourcesEnabled: Boolean - get() = component.isPrecompileDependenciesResourcesEnabled - - override fun BaseVariant.getDependencies(transitive: Boolean, filter: (ComponentIdentifier) -> Boolean): Collection { - val all = getArtifactCollection( - AndroidArtifacts.ConsumedConfigType.RUNTIME_CLASSPATH, - AndroidArtifacts.ArtifactScope.ALL, - AndroidArtifacts.ArtifactType.CLASSES_JAR - ).filter { result -> - filter(result.id.componentIdentifier) - }.associateBy { - it.id.componentIdentifier.displayName - } - val result = if (!transitive) { - runtimeConfiguration.incoming.resolutionResult.root.dependencies.filterIsInstance().mapNotNull { - it.selected.id.displayName.takeIf { id -> id in all.keys } - }.associateWith { - all[it]!! - } - } else { - all - } - return result.values.toSet() - } - - override val Context.task: TransformTask - get() = javaClass.getDeclaredField("this$1").apply { - isAccessible = true - }.get(this).run { - javaClass.getDeclaredField("this$0").apply { - isAccessible = true - }.get(this) - } as TransformTask - - override val Project.aapt2Enabled: Boolean - get() = true - -} diff --git a/booster-android-gradle-v7_3/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_3/V73Factory.kt b/booster-android-gradle-v7_3/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_3/V73Factory.kt deleted file mode 100644 index 4af833baa..000000000 --- a/booster-android-gradle-v7_3/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_3/V73Factory.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.didiglobal.booster.android.gradle.v7_3 - -import com.android.repository.Revision -import com.didiglobal.booster.gradle.AGPInterface -import com.didiglobal.booster.gradle.AGPInterfaceFactory -import com.google.auto.service.AutoService - -@AutoService(AGPInterfaceFactory::class) -class V73Factory : AGPInterfaceFactory { - - override val revision: Revision = Revision(7, 3, 0) - - override fun newAGPInterface(): AGPInterface = V73 - -} diff --git a/booster-android-gradle-v7_4/README.md b/booster-android-gradle-v7_4/README.md deleted file mode 100644 index 1e94458f5..000000000 --- a/booster-android-gradle-v7_4/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# booster-android-gradle-v7_4 - -This module is an implementation of [booster-android-gradle-api](../booster-android-gradle-api) for Android gradle plugin above 7.4 - -本模块是 [booster-android-gradle-api](../booster-android-gradle-api) 针对 Android gradle plugin 7.4 以上版本的实现。 - diff --git a/booster-android-gradle-v7_4/build.gradle b/booster-android-gradle-v7_4/build.gradle deleted file mode 100644 index 25f86ff60..000000000 --- a/booster-android-gradle-v7_4/build.gradle +++ /dev/null @@ -1,27 +0,0 @@ -apply plugin: 'java-gradle-plugin' - -apply from: "$rootDir/gradle/booster.gradle" -apply from: "$rootDir/gradle/integration-test.gradle" -apply from: "$rootDir/gradle/functional-test.gradle" - -dependencies { - kapt 'com.google.auto.service:auto-service:1.0' - api 'com.google.auto.service:auto-service:1.0' - api project(':booster-android-gradle-compat') - compileOnly 'com.android.tools:repository:30.0.0' - compileOnly 'com.android.tools:common:30.0.0' - compileOnly 'com.android.tools:sdklib:30.0.0' - compileOnly 'com.android.tools.build:gradle:7.4.2' - testImplementation 'com.android.tools.build:gradle:7.4.2' - testImplementation 'com.android.tools:common:30.0.0' - testImplementation 'io.bootstage.testkit:testkit-gradle-plugin:1.1.0' - testImplementation project(':booster-build') -} - -jar { - exclude('com/android/sdklib/BuildToolInfo.class') -} - -gradlePlugin { - testSourceSets sourceSets.functionalTest, sourceSets.integrationTest -} \ No newline at end of file diff --git a/booster-android-gradle-v7_4/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v7_4/V74IntegrationTest.kt b/booster-android-gradle-v7_4/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v7_4/V74IntegrationTest.kt deleted file mode 100644 index 0e38cbe98..000000000 --- a/booster-android-gradle-v7_4/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v7_4/V74IntegrationTest.kt +++ /dev/null @@ -1,480 +0,0 @@ -@file:Suppress("DEPRECATION") - -package com.didiglobal.booster.android.gradle.v7_4 - -import com.android.build.gradle.AppExtension -import com.android.build.gradle.BaseExtension -import com.android.build.gradle.LibraryExtension -import com.android.build.gradle.api.BaseVariant -import com.didiglobal.booster.gradle.AGP -import com.didiglobal.booster.gradle.getAndroid -import com.didiglobal.booster.kotlinx.search -import io.bootstage.testkit.gradle.Case -import io.bootstage.testkit.gradle.TestCase -import io.bootstage.testkit.gradle.VariantTestCase -import io.bootstage.testkit.gradle.rules.GradleExecutor -import io.bootstage.testkit.gradle.rules.LocalProperties -import io.bootstage.testkit.gradle.rules.copyFromResource -import io.bootstage.testkit.gradle.rules.rule -import org.gradle.api.Project -import org.junit.Before -import org.junit.Rule -import org.junit.rules.TemporaryFolder -import org.junit.rules.TestRule -import java.io.File -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertNotNull -import kotlin.test.assertTrue -import kotlin.test.fail - -private val MIN_SDK_VERSION = System.getProperty("android.minsdk.version").toInt() - -private const val TARGET_SDK_VERSION = 30 - -private val ARGS = System.getProperty("gradle.args").split("\\s+".toRegex()) + listOf( - "-Pbooster_version=${Build.VERSION}", - "-Pandroid_gradle_version=7.4.2", - "-Pcompile_sdk_version=30", - "-Pbuild_tools_version=29.0.2", - "-Pmin_sdk_version=${MIN_SDK_VERSION}", - "-Ptarget_sdk_version=${TARGET_SDK_VERSION}" -) - -@Suppress("RemoveCurlyBracesFromTemplate", "FunctionName") -abstract class V74IntegrationTest(private val isLib: Boolean) { - - private val projectDir = TemporaryFolder() - - @get:Rule - val ruleChain: TestRule = rule(projectDir) { - rule(LocalProperties(projectDir::getRoot)) { - GradleExecutor(projectDir::getRoot, "7.5", *ARGS.toTypedArray()) - } - } - - @Before - fun setup() { - projectDir.copyFromResource("${if (isLib) "lib" else "app"}.gradle", "build.gradle") - projectDir.copyFromResource("buildSrc") - projectDir.copyFromResource("src") - projectDir.newFile("gradle.properties").writeText("org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=2g") - assertEquals(7, AGP.revision.major) - assertEquals(4, AGP.revision.minor) - } - - @Test - @Case(ScopeFullWithFeaturesTest::class) - fun `test AGPInterface#scopeFullWithFeatures`() = Unit - - @Test - @Case(ScopeFullLibraryWithFeaturesTest::class) - fun `test AGPInterface#scopeFullLibraryWithFeatures`() = Unit - - @Test - @Case(ProjectTest::class) - fun `test AGPInterface#project`() = Unit - - @Test - @Case(JavaCompilerTaskTestUnit::class) - fun `test AGPInterface#javaCompilerTask`() = Unit - - @Test - @Case(PreBuildTaskTestUnit::class) - fun `test AGPInterface#preBuildTask`() = Unit - - @Test - @Case(AssembleTaskTestUnit::class) - fun `test AGPInterface#assembleTask`() = Unit - - @Test - @Case(MergeAssetsTaskTestUnit::class) - fun `test AGPInterface#mergeAssetsTask`() = Unit - - @Test - @Case(MergeResourcesTaskTestUnit::class) - fun `test AGPInterface#mergeResources`() = Unit - - @Test - @Case(GetTaskNameTestUnit::class) - fun `test AGPInterface#getTaskName(String)`() = Unit - - @Test - @Case(GetTaskName2TestUnit::class) - fun `test AGPInterface#getTaskName(String, String)`() = Unit - - @Test - @Case(VariantDataTestUnit::class) - fun `test AGPInterface#variantData`() = Unit - - @Test - @Case(OriginalApplicationIdTestUnit::class) - fun `test AGPInterface#originalApplicationId`() = Unit - - @Test - @Case(HasDynamicFeatureTestUnit::class) - fun `test AGPInterface#hasDynamicFeature`() = Unit - - @Test - @Case(RawAndroidResourcesTestUnit::class) - fun `test AGPInterface#rawAndroidResources`() = Unit - - @Test - @Case(AllArtifactsTestUnit::class) - fun `test AGPInterface#allArtifacts`() = Unit - - @Test - @Case(MinSdkVersionTestUnit::class) - fun `test AGPInterface#minSdkVersion`() = Unit - - @Test - @Case(TargetSdkVersionTestUnit::class) - fun `test AGPInterface#targetSdkVersion`() = Unit - - @Test - @Case(AarTestUnit::class) - fun `test AGPInterface#aar`() { - } - - @Test - @Case(ApkTestUnit::class) - fun `test AGPInterface#apk`() { - } - - @Test - @Case(MergedManifestsTestUnit::class) - fun `test AGPInterface#mergedManifests`() { - } - - @Test - @Case(MergedResourcesTestUnit::class) - fun `test AGPInterface#mergedRes`() { - } - - @Test - @Case(MergedAssetsTestUnit::class) - fun `test AGPInterface#mergedAssets`() { - } - - @Test - @Case(ProcessedResTestUnit::class) - fun `test AGPInterface#processedRes`() { - } - - @Test - @Case(SymbolListTestUnit::class) - fun `test AGPInterface#symbolList`() { - } - - @Test - @Case(SymbolListWithPackageNameTestUnit::class) - fun `test AGPInterface#symbolListWithPackageName`() { - } - - @Test - @Case(AllClassesTestUnit::class) - fun `test AGPInterface#allClasses`() { - } - -// @Test -// @Case(BuildToolsTestUnit::class) -// fun `test AGPInterface#buildTools`() { -// } - -} - -class V74AppIntegrationTest : V74IntegrationTest(false) - -class V74LibIntegrationTest : V74IntegrationTest(true) - -class ScopeFullWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("PROJECT,SUB_PROJECTS,EXTERNAL_LIBRARIES,FEATURES", AGP.scopeFullWithFeatures.joinToString(",")) - } -} - -class ScopeFullLibraryWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("FEATURES,PROJECT", AGP.scopeFullLibraryWithFeatures.joinToString(",")) - } -} - -class ProjectTest : TestCase { - override fun apply(project: Project) { - val assert: (BaseVariant) -> Unit = { variant -> - assertEquals(project, AGP.run { variant.project }) - } - project.afterEvaluate { - when (val android = project.getAndroid()) { - is AppExtension -> android.applicationVariants.forEach(assert) - is LibraryExtension -> android.libraryVariants.forEach(assert) - } - } - } -} - -class JavaCompilerTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.javaCompilerTask }) - } -} - -class PreBuildTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.preBuildTask }) - } -} - -class AssembleTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.assembleTask }) - } -} - -class MergeAssetsTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeAssetsTask }) - } -} - -class MergeResourcesTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeResourcesTask }) - } -} - -class GetTaskNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("assemble${variant.name.capitalize()}", AGP.run { variant.getTaskName("assemble") }) - } -} - - -class GetTaskName2TestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("merge${variant.name.capitalize()}Resources", AGP.run { variant.getTaskName("merge", "Resources") }) - } -} - -class VariantDataTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.variantData }) - } -} - -class OriginalApplicationIdTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - assertNotNull(AGP.run { variant.originalApplicationId }) - } - } -} - -class HasDynamicFeatureTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertFalse(AGP.run { variant.hasDynamicFeature }) - } -} - -class RawAndroidResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val rawAndroidResources = AGP.run { variant.rawAndroidResources } - assertNotNull(rawAndroidResources) - if (rawAndroidResources.isEmpty()) { - fail("rawAndroidResources is empty") - } - rawAndroidResources.forEach { - println(" - ${it.path}") - } - } - } -} - -class AllArtifactsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val allArtifacts = AGP.run { variant.allArtifacts } - assertNotNull(allArtifacts) - if (allArtifacts.isEmpty()) { - fail("allArtifacts is empty") - } - allArtifacts.forEach { (k, v) -> - println(" - $k => $v") - } - } - } -} - -class MinSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val minSdkVersion = AGP.run { variant.minSdkVersion } - assertNotNull(minSdkVersion) - assertEquals(MIN_SDK_VERSION, minSdkVersion.apiLevel) - } -} - -class TargetSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - val targetSdkVersion = AGP.run { variant.targetSdkVersion } - assertNotNull(targetSdkVersion) - assertEquals(TARGET_SDK_VERSION, targetSdkVersion.apiLevel) - } -} - -class AarTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.library")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val aar = AGP.run { variant.aar }.search { - it.extension == "aar" - } - if (aar.isEmpty()) { - fail("aar is empty") - } - aar.forEach { - println(" - ${it.path}") - } - } - } -} - -class ApkTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val apk = AGP.run { variant.apk }.search { - it.extension == "apk" - } - if (apk.isEmpty()) { - fail("apk is empty") - } - apk.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedManifestsTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedManifests = AGP.run { variant.mergedManifests }.search { - it.name == "AndroidManifest.xml" - } - if (mergedManifests.isEmpty()) { - fail("mergedManifests is empty") - } - mergedManifests.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedResources = AGP.run { variant.mergedRes } - if (mergedResources.isEmpty()) { - fail("mergedRes is empty") - } - mergedResources.forEach { - println(" - ${it.path}") - } - } - } -} - -class MergedAssetsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val mergedAssets = AGP.run { variant.mergedAssets } - if (mergedAssets.isEmpty()) { - fail("mergedAssets is empty") - } - mergedAssets.forEach { - println(" - ${it.path}") - } - } - } -} - -class ProcessedResTestUnit : VariantTestCase() { - override fun apply(project: Project) { - if (project.plugins.hasPlugin("com.android.application")) { - super.apply(project) - } - } - - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val processedRes = AGP.run { variant.processedRes }.search { - it.extension == "ap_" - } - if (processedRes.isEmpty()) { - fail("processedRes is empty") - } - processedRes.forEach { - println(" - ${it.path}") - } - } - } -} - -class SymbolListTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val symbolList = AGP.run { variant.symbolList } - if (symbolList.isEmpty()) { - fail("symbolList is empty") - } - symbolList.forEach { - println(" - ${it.path}") - } - } - } -} - -class SymbolListWithPackageNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val symbolListWithPackageName = AGP.run { variant.symbolListWithPackageName } - if (symbolListWithPackageName.isEmpty()) { - fail("symbolListWithPackageName is empty") - } - symbolListWithPackageName.forEach { - println(" - ${it.path}") - } - } - } -} - -class AllClassesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val location = AGP.run { variant.allClasses }.files - assertTrue("ALL_CLASSES: $location", location::isNotEmpty) - assertTrue("No class file found at $location") { - location.search(File::isFile).isNotEmpty() - } - } - } -} diff --git a/booster-android-gradle-v7_4/src/integrationTest/resources/app.gradle b/booster-android-gradle-v7_4/src/integrationTest/resources/app.gradle deleted file mode 100644 index aa3c5f2d6..000000000 --- a/booster-android-gradle-v7_4/src/integrationTest/resources/app.gradle +++ /dev/null @@ -1,60 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } - dependencies { - classpath "com.android.tools.build:gradle:${project.android_gradle_version}" - classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { - exclude group: 'com.google.guava' - } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" - } -} - -apply plugin: 'com.android.application' -apply plugin: 'com.didiglobal.booster' -apply plugin: 'io.bootstage.testkit' - -android { - compileSdkVersion project.compile_sdk_version as Integer - buildToolsVersion project.build_tools_version - defaultConfig { - applicationId 'com.didiglobal.booster.test' - minSdkVersion project.min_sdk_version as Integer - targetSdkVersion project.target_sdk_version as Integer - versionCode 1 - versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - buildTypes { - debug { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - flavorDimensions 'lang' - productFlavors { - en { - dimension 'lang' - applicationIdSuffix '.en' - } - cn { - dimension 'lang' - applicationIdSuffix '.cn' - } - } - lintOptions { - checkReleaseBuilds false - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} diff --git a/booster-android-gradle-v7_4/src/integrationTest/resources/buildSrc/build.gradle b/booster-android-gradle-v7_4/src/integrationTest/resources/buildSrc/build.gradle deleted file mode 100644 index 79a9b104a..000000000 --- a/booster-android-gradle-v7_4/src/integrationTest/resources/buildSrc/build.gradle +++ /dev/null @@ -1,24 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} - -dependencies { - implementation "com.android.tools.build:gradle:${project.android_gradle_version}" - implementation("com.didiglobal.booster:booster-android-gradle-api:${project.booster_version}") { - exclude group: 'com.google.guava' - } - implementation "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" -} diff --git a/booster-android-gradle-v7_4/src/integrationTest/resources/lib.gradle b/booster-android-gradle-v7_4/src/integrationTest/resources/lib.gradle deleted file mode 100644 index adc9b1ca0..000000000 --- a/booster-android-gradle-v7_4/src/integrationTest/resources/lib.gradle +++ /dev/null @@ -1,57 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } - } - dependencies { - classpath "com.android.tools.build:gradle:${project.android_gradle_version}" - classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { - exclude group: 'com.google.guava' - } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" - } -} - -apply plugin: 'com.android.library' -apply plugin: 'com.didiglobal.booster' -apply plugin: 'io.bootstage.testkit' - -android { - compileSdkVersion project.compile_sdk_version as Integer - buildToolsVersion project.build_tools_version - defaultConfig { - minSdkVersion project.min_sdk_version as Integer - targetSdkVersion project.target_sdk_version as Integer - versionCode 1 - versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - buildTypes { - debug { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - flavorDimensions 'lang' - productFlavors { - en { - dimension 'lang' - } - cn { - dimension 'lang' - } - } - lintOptions { - checkReleaseBuilds false - } -} - -repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://oss.sonatype.org/content/repositories/public/' } -} diff --git a/booster-android-gradle-v7_4/src/integrationTest/resources/src/main/AndroidManifest.xml b/booster-android-gradle-v7_4/src/integrationTest/resources/src/main/AndroidManifest.xml deleted file mode 100644 index 30800c604..000000000 --- a/booster-android-gradle-v7_4/src/integrationTest/resources/src/main/AndroidManifest.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/booster-android-gradle-v7_4/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java b/booster-android-gradle-v7_4/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java deleted file mode 100644 index 0eb4ec7b4..000000000 --- a/booster-android-gradle-v7_4/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.didiglobal.booster.android.test; - -import android.app.Activity; - -public class MainActivity extends Activity { -} \ No newline at end of file diff --git a/booster-android-gradle-v7_4/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java b/booster-android-gradle-v7_4/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java deleted file mode 100644 index 3ecfb1507..000000000 --- a/booster-android-gradle-v7_4/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.didiglobal.booster.android.test; - -import android.app.Application; - -public class TestApplication extends Application { - -} \ No newline at end of file diff --git a/booster-android-gradle-v7_4/src/integrationTest/resources/src/main/res/values/strings.xml b/booster-android-gradle-v7_4/src/integrationTest/resources/src/main/res/values/strings.xml deleted file mode 100644 index 8b2247616..000000000 --- a/booster-android-gradle-v7_4/src/integrationTest/resources/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - Test - \ No newline at end of file diff --git a/booster-android-gradle-v7_4/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_4/V74.kt b/booster-android-gradle-v7_4/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_4/V74.kt deleted file mode 100644 index bf3899b3a..000000000 --- a/booster-android-gradle-v7_4/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_4/V74.kt +++ /dev/null @@ -1,333 +0,0 @@ -package com.didiglobal.booster.android.gradle.v7_4 - -import com.android.build.api.artifact.Artifact -import com.android.build.api.artifact.MultipleArtifact -import com.android.build.api.artifact.SingleArtifact -import com.android.build.api.artifact.impl.ArtifactsImpl -import com.android.build.api.component.impl.ComponentImpl -import com.android.build.api.transform.Context -import com.android.build.api.transform.QualifiedContent -import com.android.build.api.variant.impl.TaskProviderBasedDirectoryEntryImpl -import com.android.build.gradle.api.ApplicationVariant -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.LibraryVariant -import com.android.build.gradle.internal.api.BaseVariantImpl -import com.android.build.gradle.internal.api.artifact.SourceArtifactType -import com.android.build.gradle.internal.pipeline.TransformManager -import com.android.build.gradle.internal.pipeline.TransformTask -import com.android.build.gradle.internal.publishing.AndroidArtifacts -import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactScope -import com.android.build.gradle.internal.scope.BuildArtifactType -import com.android.build.gradle.internal.scope.InternalArtifactType -import com.android.build.gradle.internal.scope.InternalMultipleArtifactType -import com.android.build.gradle.internal.tasks.factory.GlobalTaskCreationConfigImpl -import com.android.build.gradle.internal.variant.BaseVariantData -import com.android.builder.core.DefaultApiVersion -import com.android.builder.model.ApiVersion -import com.android.sdklib.BuildToolInfo -import com.didiglobal.booster.gradle.AGPInterface -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.artifacts.ArtifactCollection -import org.gradle.api.artifacts.component.ComponentIdentifier -import org.gradle.api.artifacts.result.ResolvedArtifactResult -import org.gradle.api.artifacts.result.ResolvedDependencyResult -import org.gradle.api.file.ConfigurableFileCollection -import org.gradle.api.file.FileCollection -import org.gradle.api.file.FileSystemLocation -import org.gradle.api.tasks.TaskProvider -import java.io.File -import java.util.TreeMap - -@Suppress("UnstableApiUsage") -private val SINGLE_ARTIFACT_TYPES = arrayOf( - BuildArtifactType::class, - InternalArtifactType::class, - SingleArtifact::class, - SourceArtifactType::class -).map { - it.sealedSubclasses -}.flatten().map { - it.objectInstance as Artifact.Single -}.associateBy { - it.javaClass.simpleName -} - -private val MULTIPLE_ARTIFACT_TYPES = arrayOf( - MultipleArtifact::class, - InternalMultipleArtifactType::class -).map { - it.sealedSubclasses -}.flatten().map { - it.objectInstance as Artifact.Multiple -}.associateBy { - it.javaClass.simpleName -} - -@Suppress("DEPRECATION") -internal object V74 : AGPInterface { - - private val BaseVariant.component: ComponentImpl<*> - get() = BaseVariantImpl::class.java.getDeclaredField("component").apply { - isAccessible = true - }.get(this) as ComponentImpl<*> - - @Suppress("UnstableApiUsage") - private fun BaseVariant.getFinalArtifactFiles(type: Artifact.Single): FileCollection { - return try { - project.objects.fileCollection().from(artifacts.get(type)) - } catch (e: Throwable) { - project.objects.fileCollection().builtBy(artifacts.get(type)) - } - } - - @Suppress("UnstableApiUsage") - private fun BaseVariant.getFinalArtifactFiles(type: Artifact.Multiple): FileCollection { - return try { - project.objects.fileCollection().from(artifacts.getAll(type)) - } catch (e: Throwable) { - project.objects.fileCollection().builtBy(artifacts.getAll(type)) - } - } - - @Suppress("UnstableApiUsage") - private val BaseVariant.artifacts: ArtifactsImpl - get() = component.artifacts - - override val scopeFullWithFeatures: MutableSet - get() = TransformManager.SCOPE_FULL_WITH_FEATURES - - override val scopeFullLibraryWithFeatures: MutableSet - get() = (TransformManager.SCOPE_FEATURES + QualifiedContent.Scope.PROJECT).toMutableSet() - - override val BaseVariant.project: Project - get() = component.variantDependencies.run { - javaClass.getDeclaredField("project").apply { - isAccessible = true - }.get(this) as Project - } - - override val BaseVariant.javaCompilerTaskProvider: TaskProvider - get() = javaCompileProvider - - override val BaseVariant.preBuildTaskProvider: TaskProvider - get() = preBuildProvider - - override val BaseVariant.assembleTaskProvider: TaskProvider - get() = assembleProvider - - override val BaseVariant.mergeAssetsTaskProvider: TaskProvider - get() = mergeAssetsProvider - - override val BaseVariant.mergeResourcesTaskProvider: TaskProvider - get() = try { - project.tasks.named(getTaskName("merge", "Resources")) - } catch (e: Throwable) { - mergeResourcesProvider - } - - override val BaseVariant.mergeNativeLibsTaskProvider: TaskProvider - get() = project.tasks.named(getTaskName("merge", "NativeLibs")) - - override val BaseVariant.processJavaResourcesTaskProvider: TaskProvider - get() = processJavaResourcesProvider - - override fun BaseVariant.getTaskName(prefix: String): String { - return component.computeTaskName(prefix) - } - - override fun BaseVariant.getTaskName(prefix: String, suffix: String): String { - return component.computeTaskName(prefix, suffix) - } - - override val BaseVariant.variantData: BaseVariantData - get() = javaClass.getDeclaredMethod("getVariantData").apply { - isAccessible = true - }.invoke(this) as BaseVariantData - - @Suppress("DEPRECATION") - private val BaseVariant.globalScope: GlobalTaskCreationConfigImpl - get() = component.global as GlobalTaskCreationConfigImpl - - override val BaseVariant.originalApplicationId: String - get() = component.namespace.get() - - override val BaseVariant.hasDynamicFeature: Boolean - get() = component.global.hasDynamicFeatures - - override val BaseVariant.rawAndroidResources: FileCollection - get() { - val allRes: ConfigurableFileCollection = component.services.fileCollection() - - allRes.from(component.variantDependencies.getArtifactCollection( - AndroidArtifacts.ConsumedConfigType.RUNTIME_CLASSPATH, - ArtifactScope.ALL, - AndroidArtifacts.ArtifactType.ANDROID_RES - ).artifactFiles) - - allRes.from(component.services.fileCollection(variantData.extraGeneratedResFolders) - .builtBy(listOfNotNull(variantData.extraGeneratedResFolders.builtBy))) - - component.taskContainer.generateApkDataTask?.let { - allRes.from(artifacts.get(InternalArtifactType.MICRO_APK_RES)) - } - - allRes.from(component.sources.res.getVariantSources().map { allSources -> - allSources.getEntries().map { - if (it is TaskProviderBasedDirectoryEntryImpl) { - it.directoryProvider - } else { - it.asFiles(component.services.provider { - component.services.projectInfo.projectDirectory - }) - } - } - }) - - return allRes - } - - override val BaseVariant.localAndroidResources: FileCollection - get() = component.services.fileCollection().from(component.sources.res.getLocalSources().values.map { - it.map { dirs -> - dirs.map { dir -> - dir.asFileTree - }.reduce { acc, dir -> - acc.plus(dir) - } - } - }) - - override fun BaseVariant.getArtifactCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): ArtifactCollection { - return component.variantDependencies.getArtifactCollection(configType, scope, artifactType) - } - - override fun BaseVariant.getArtifactFileCollection( - configType: AndroidArtifacts.ConsumedConfigType, - scope: ArtifactScope, - artifactType: AndroidArtifacts.ArtifactType - ): FileCollection { - return component.variantDependencies.getArtifactFileCollection(configType, scope, artifactType) - } - - override val BaseVariant.allArtifacts: Map - get() = TreeMap().also { all -> - SINGLE_ARTIFACT_TYPES.entries.associateTo(all) { (name, type) -> - val artifacts: FileCollection by lazy { - getFinalArtifactFiles(type) - } - name to artifacts - } - MULTIPLE_ARTIFACT_TYPES.entries.associateTo(all) { (name, type) -> - val artifacts: FileCollection by lazy { - getFinalArtifactFiles(type) - } - name to artifacts - } - } - - override val BaseVariant.minSdkVersion: ApiVersion - get() = DefaultApiVersion(component.minSdkVersion.apiLevel) - - override val BaseVariant.targetSdkVersion: ApiVersion - get() = DefaultApiVersion(component.targetSdkVersion.apiLevel) - - override val BaseVariant.isApplication: Boolean - get() = component.componentType.isApk - - override val BaseVariant.isLibrary: Boolean - get() = component.componentType.isAar - - override val BaseVariant.isDynamicFeature: Boolean - get() = component.componentType.isDynamicFeature - - override val BaseVariant.aar: FileCollection - get() = getFinalArtifactFiles(SingleArtifact.AAR) - - override val BaseVariant.apk: FileCollection - get() = getFinalArtifactFiles(SingleArtifact.APK) - - override val BaseVariant.mergedManifests: FileCollection - get() = getFinalArtifactFiles(SingleArtifact.MERGED_MANIFEST) - - override val BaseVariant.mergedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.MERGED_RES) - - override val BaseVariant.mergedNativeLibs: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.MERGED_NATIVE_LIBS) - - override val BaseVariant.mergedAssets: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.COMPRESSED_ASSETS) - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.LIBRARY_ASSETS) - else -> TODO("Unsupported variant type: $name") - } - - override val BaseVariant.processedRes: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.PROCESSED_RES) - - override val BaseVariant.symbolList: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.RUNTIME_SYMBOL_LIST) - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.COMPILE_SYMBOL_LIST) - else -> TODO("Unsupported variant type : $name") - } - - override val BaseVariant.symbolListWithPackageName: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.SYMBOL_LIST_WITH_PACKAGE_NAME) - - override val BaseVariant.dataBindingDependencyArtifacts: FileCollection - get() = getFinalArtifactFiles(InternalArtifactType.DATA_BINDING_DEPENDENCY_ARTIFACTS) - - override val BaseVariant.allClasses: FileCollection - get() = when (this) { - is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.JAVAC) + project.files("build${File.separator}tmp${File.separator}kotlin-classes${File.separator}${dirName}") - is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.AAR_MAIN_JAR) - else -> project.files() - } - - override val BaseVariant.buildTools: BuildToolInfo - get() = globalScope.versionedSdkLoader.get().buildToolInfoProvider.get() - - override val BaseVariant.isPrecompileDependenciesResourcesEnabled: Boolean - get() = component.androidResourcesCreationConfig?.isPrecompileDependenciesResourcesEnabled == true - - override fun BaseVariant.getDependencies(transitive: Boolean, filter: (ComponentIdentifier) -> Boolean): Collection { - val all = getArtifactCollection( - AndroidArtifacts.ConsumedConfigType.RUNTIME_CLASSPATH, - AndroidArtifacts.ArtifactScope.ALL, - AndroidArtifacts.ArtifactType.CLASSES_JAR - ).filter { result -> - filter(result.id.componentIdentifier) - }.associateBy { - it.id.componentIdentifier.displayName - } - val result = if (!transitive) { - runtimeConfiguration.incoming.resolutionResult.root.dependencies.filterIsInstance().mapNotNull { - it.selected.id.displayName.takeIf { id -> id in all.keys } - }.associateWith { - all[it]!! - } - } else { - all - } - return result.values.toSet() - } - - override val Context.task: TransformTask - get() = javaClass.getDeclaredField("this$1").apply { - isAccessible = true - }.get(this).run { - javaClass.getDeclaredField("this$0").apply { - isAccessible = true - }.get(this) - } as TransformTask - - override val Project.aapt2Enabled: Boolean - get() = true - -} diff --git a/booster-android-gradle-v7_4/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_4/V74Factory.kt b/booster-android-gradle-v7_4/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_4/V74Factory.kt deleted file mode 100644 index 0ab0810ef..000000000 --- a/booster-android-gradle-v7_4/src/main/kotlin/com/didiglobal/booster/android/gradle/v7_4/V74Factory.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.didiglobal.booster.android.gradle.v7_4 - -import com.android.repository.Revision -import com.didiglobal.booster.gradle.AGPInterface -import com.didiglobal.booster.gradle.AGPInterfaceFactory -import com.google.auto.service.AutoService - -@AutoService(AGPInterfaceFactory::class) -class V74Factory : AGPInterfaceFactory { - - override val revision: Revision = Revision(7, 4, 2) - - override fun newAGPInterface(): AGPInterface = V74 - -} diff --git a/booster-android-gradle-v7_0/README.md b/booster-android-gradle-v8_0/README.md similarity index 66% rename from booster-android-gradle-v7_0/README.md rename to booster-android-gradle-v8_0/README.md index bb2f24ac0..1543df551 100644 --- a/booster-android-gradle-v7_0/README.md +++ b/booster-android-gradle-v8_0/README.md @@ -1,6 +1,6 @@ -# booster-android-gradle-v7_0 +# booster-android-gradle-v8_0 -This module is an implementation of [booster-android-gradle-api](../booster-android-gradle-api) for Android gradle plugin above 7.0 +This module is an implementation of [booster-android-gradle-api](../booster-android-gradle-api) for Android gradle plugin above 8.0 -本模块是 [booster-android-gradle-api](../booster-android-gradle-api) 针对 Android gradle plugin 7.0 以上版本的实现。 +本模块是 [booster-android-gradle-api](../booster-android-gradle-api) 针对 Android gradle plugin 8.0 以上版本的实现。 diff --git a/booster-android-gradle-v7_0/build.gradle b/booster-android-gradle-v8_0/build.gradle similarity index 81% rename from booster-android-gradle-v7_0/build.gradle rename to booster-android-gradle-v8_0/build.gradle index 06c24957e..2c4460414 100644 --- a/booster-android-gradle-v7_0/build.gradle +++ b/booster-android-gradle-v8_0/build.gradle @@ -11,11 +11,12 @@ dependencies { compileOnly 'com.android.tools:repository:30.0.0' compileOnly 'com.android.tools:common:30.0.0' compileOnly 'com.android.tools:sdklib:30.0.0' - compileOnly 'com.android.tools.build:gradle:7.0.0' - testImplementation 'com.android.tools.build:gradle:7.0.0' + compileOnly 'com.android.tools.build:gradle:8.0.0' + testImplementation 'com.android.tools.build:gradle:8.0.0' testImplementation 'com.android.tools:common:30.0.0' - testImplementation 'io.bootstage.testkit:testkit-gradle-plugin:1.1.0' + testImplementation 'io.bootstage.testkit:testkit-gradle-plugin:2.1.0' testImplementation project(':booster-build') + testImplementation project(':booster-android-gradle-api') } jar { diff --git a/booster-android-gradle-v7_0/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v7_0/V70IntegrationTest.kt b/booster-android-gradle-v8_0/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v8_0/V80IntegrationTest.kt similarity index 57% rename from booster-android-gradle-v7_0/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v7_0/V70IntegrationTest.kt rename to booster-android-gradle-v8_0/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v8_0/V80IntegrationTest.kt index f6447e12e..8017a07df 100644 --- a/booster-android-gradle-v7_0/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v7_0/V70IntegrationTest.kt +++ b/booster-android-gradle-v8_0/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v8_0/V80IntegrationTest.kt @@ -1,13 +1,17 @@ @file:Suppress("DEPRECATION") -package com.didiglobal.booster.android.gradle.v7_0 +package com.didiglobal.booster.android.gradle.v8_0 -import com.android.build.gradle.AppExtension -import com.android.build.gradle.BaseExtension -import com.android.build.gradle.LibraryExtension -import com.android.build.gradle.api.BaseVariant +import com.android.build.api.dsl.CommonExtension +import com.android.build.api.variant.AndroidComponentsExtension +import com.android.build.api.variant.TestAndroidComponentsExtension +import com.android.build.api.variant.Variant +import com.android.build.api.variant.VariantBuilder import com.didiglobal.booster.gradle.AGP -import com.didiglobal.booster.gradle.getAndroid +import com.didiglobal.booster.gradle.assembleTaskProvider +import com.didiglobal.booster.gradle.getAndroidComponents +import com.didiglobal.booster.gradle.project +import com.didiglobal.booster.kotlinx.capitalized import com.didiglobal.booster.kotlinx.search import io.bootstage.testkit.gradle.Case import io.bootstage.testkit.gradle.TestCase @@ -35,22 +39,22 @@ private const val TARGET_SDK_VERSION = 30 private val ARGS = System.getProperty("gradle.args").split("\\s+".toRegex()) + listOf( "-Pbooster_version=${Build.VERSION}", - "-Pandroid_gradle_version=7.0.0", + "-Pandroid_gradle_version=8.0.0", "-Pcompile_sdk_version=30", "-Pbuild_tools_version=29.0.2", - "-Pmin_sdk_version=${MIN_SDK_VERSION}", - "-Ptarget_sdk_version=${TARGET_SDK_VERSION}" + "-Pmin_sdk_version=$MIN_SDK_VERSION", + "-Ptarget_sdk_version=$TARGET_SDK_VERSION" ) @Suppress("RemoveCurlyBracesFromTemplate", "FunctionName") -abstract class V70IntegrationTest(private val isLib: Boolean) { +abstract class V80IntegrationTest(private val isLib: Boolean) { private val projectDir = TemporaryFolder() @get:Rule val ruleChain: TestRule = rule(projectDir) { rule(LocalProperties(projectDir::getRoot)) { - GradleExecutor(projectDir::getRoot, "7.0.2", *ARGS.toTypedArray()) + GradleExecutor(projectDir::getRoot, "8.0", *ARGS.toTypedArray()) } } @@ -60,18 +64,10 @@ abstract class V70IntegrationTest(private val isLib: Boolean) { projectDir.copyFromResource("buildSrc") projectDir.copyFromResource("src") projectDir.newFile("gradle.properties").writeText("org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=2g") - assertEquals(7, AGP.revision.major) + assertEquals(8, AGP.revision.major) assertEquals(0, AGP.revision.minor) } - @Test - @Case(ScopeFullWithFeaturesTest::class) - fun `test AGPInterface#scopeFullWithFeatures`() = Unit - - @Test - @Case(ScopeFullLibraryWithFeaturesTest::class) - fun `test AGPInterface#scopeFullLibraryWithFeatures`() = Unit - @Test @Case(ProjectTest::class) fun `test AGPInterface#project`() = Unit @@ -96,82 +92,6 @@ abstract class V70IntegrationTest(private val isLib: Boolean) { @Case(MergeResourcesTaskTestUnit::class) fun `test AGPInterface#mergeResources`() = Unit - @Test - @Case(GetTaskNameTestUnit::class) - fun `test AGPInterface#getTaskName(String)`() = Unit - - @Test - @Case(GetTaskName2TestUnit::class) - fun `test AGPInterface#getTaskName(String, String)`() = Unit - - @Test - @Case(VariantDataTestUnit::class) - fun `test AGPInterface#variantData`() = Unit - - @Test - @Case(OriginalApplicationIdTestUnit::class) - fun `test AGPInterface#originalApplicationId`() = Unit - - @Test - @Case(HasDynamicFeatureTestUnit::class) - fun `test AGPInterface#hasDynamicFeature`() = Unit - - @Test - @Case(RawAndroidResourcesTestUnit::class) - fun `test AGPInterface#rawAndroidResources`() = Unit - - @Test - @Case(AllArtifactsTestUnit::class) - fun `test AGPInterface#allArtifacts`() = Unit - - @Test - @Case(MinSdkVersionTestUnit::class) - fun `test AGPInterface#minSdkVersion`() = Unit - - @Test - @Case(TargetSdkVersionTestUnit::class) - fun `test AGPInterface#targetSdkVersion`() = Unit - - @Test - @Case(AarTestUnit::class) - fun `test AGPInterface#aar`() { - } - - @Test - @Case(ApkTestUnit::class) - fun `test AGPInterface#apk`() { - } - - @Test - @Case(MergedManifestsTestUnit::class) - fun `test AGPInterface#mergedManifests`() { - } - - @Test - @Case(MergedResourcesTestUnit::class) - fun `test AGPInterface#mergedRes`() { - } - - @Test - @Case(MergedAssetsTestUnit::class) - fun `test AGPInterface#mergedAssets`() { - } - - @Test - @Case(ProcessedResTestUnit::class) - fun `test AGPInterface#processedRes`() { - } - - @Test - @Case(SymbolListTestUnit::class) - fun `test AGPInterface#symbolList`() { - } - - @Test - @Case(SymbolListWithPackageNameTestUnit::class) - fun `test AGPInterface#symbolListWithPackageName`() { - } - @Test @Case(AllClassesTestUnit::class) fun `test AGPInterface#allClasses`() { @@ -179,100 +99,102 @@ abstract class V70IntegrationTest(private val isLib: Boolean) { } -class V70AppIntegrationTest : V70IntegrationTest(false) +class V80AppIntegrationTest : V80IntegrationTest(false) -class V70LibIntegrationTest : V70IntegrationTest(true) +class V80LibIntegrationTest : V80IntegrationTest(true) -class ScopeFullWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("PROJECT,SUB_PROJECTS,EXTERNAL_LIBRARIES,FEATURES", AGP.scopeFullWithFeatures.joinToString(",")) - } -} - -class ScopeFullLibraryWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("FEATURES,PROJECT", AGP.scopeFullLibraryWithFeatures.joinToString(",")) - } -} class ProjectTest : TestCase { override fun apply(project: Project) { - val assert: (BaseVariant) -> Unit = { variant -> + val assert: (Variant) -> Unit = { variant -> assertEquals(project, AGP.run { variant.project }) } - project.afterEvaluate { - when (val android = project.getAndroid()) { - is AppExtension -> android.applicationVariants.forEach(assert) - is LibraryExtension -> android.libraryVariants.forEach(assert) - } - } + project.getAndroidComponents>().onVariants(callback = assert) } } class JavaCompilerTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.javaCompilerTask }) + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + assertNotNull(AGP.run { + variant.javaCompilerTask + }) + } } } class PreBuildTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.preBuildTask }) + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + assertNotNull(AGP.run { variant.preBuildTask }) + } } } class AssembleTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.assembleTask }) + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + assertNotNull(AGP.run { variant.assembleTask }) + } } } class MergeAssetsTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeAssetsTask }) + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + assertNotNull(AGP.run { variant.mergeAssetsTask }) + } } } class MergeResourcesTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeResourcesTask }) + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + assertNotNull(AGP.run { variant.mergeResourcesTask }) + } } } class GetTaskNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("assemble${variant.name.capitalize()}", AGP.run { variant.getTaskName("assemble") }) + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + assertEquals("assemble${variant.name.capitalized()}", AGP.run { variant.getTaskName("assemble") }) + } } } class GetTaskName2TestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("merge${variant.name.capitalize()}Resources", AGP.run { variant.getTaskName("merge", "Resources") }) + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + assertEquals("merge${variant.name.capitalized()}Resources", AGP.run { variant.getTaskName("merge", "Resources") }) + } } } class VariantDataTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { + override fun apply(variant: Variant) { assertNotNull(AGP.run { variant.variantData }) } } class OriginalApplicationIdTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.originalApplicationId }) + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + assertNotNull(AGP.run { variant.originalApplicationId }) + } } } class HasDynamicFeatureTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { + override fun apply(variant: Variant) { assertFalse(AGP.run { variant.hasDynamicFeature }) } } class RawAndroidResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val rawAndroidResources = AGP.run { variant.rawAndroidResources } assertNotNull(rawAndroidResources) if (rawAndroidResources.isEmpty) { @@ -286,8 +208,8 @@ class RawAndroidResourcesTestUnit : VariantTestCase() { } class AllArtifactsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val allArtifacts = AGP.run { variant.allArtifacts } assertNotNull(allArtifacts) if (allArtifacts.isEmpty()) { @@ -301,7 +223,7 @@ class AllArtifactsTestUnit : VariantTestCase() { } class MinSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { + override fun apply(variant: Variant) { val minSdkVersion = AGP.run { variant.minSdkVersion } assertNotNull(minSdkVersion) assertEquals(MIN_SDK_VERSION, minSdkVersion.apiLevel) @@ -309,7 +231,7 @@ class MinSdkVersionTestUnit : VariantTestCase() { } class TargetSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { + override fun apply(variant: Variant) { val targetSdkVersion = AGP.run { variant.targetSdkVersion } assertNotNull(targetSdkVersion) assertEquals(TARGET_SDK_VERSION, targetSdkVersion.apiLevel) @@ -323,8 +245,8 @@ class AarTestUnit : VariantTestCase() { } } - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val aar = AGP.run { variant.aar }.search { it.extension == "aar" } @@ -345,8 +267,8 @@ class ApkTestUnit : VariantTestCase() { } } - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val apk = AGP.run { variant.apk }.search { it.extension == "apk" } @@ -367,8 +289,8 @@ class MergedManifestsTestUnit : VariantTestCase() { } } - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val mergedManifests = AGP.run { variant.mergedManifests }.search { it.name == "AndroidManifest.xml" } @@ -383,8 +305,8 @@ class MergedManifestsTestUnit : VariantTestCase() { } class MergedResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val mergedResources = AGP.run { variant.mergedRes } if (mergedResources.isEmpty) { fail("mergedRes is empty") @@ -397,10 +319,10 @@ class MergedResourcesTestUnit : VariantTestCase() { } class MergedAssetsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val mergedAssets = AGP.run { variant.mergedAssets } - if (mergedAssets.isEmpty) { + if (mergedAssets.isEmpty()) { fail("mergedAssets is empty") } mergedAssets.forEach { @@ -417,8 +339,8 @@ class ProcessedResTestUnit : VariantTestCase() { } } - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val processedRes = AGP.run { variant.processedRes }.search { it.extension == "ap_" } @@ -433,8 +355,8 @@ class ProcessedResTestUnit : VariantTestCase() { } class SymbolListTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val symbolList = AGP.run { variant.symbolList } if (symbolList.isEmpty) { fail("symbolList is empty") @@ -447,8 +369,8 @@ class SymbolListTestUnit : VariantTestCase() { } class SymbolListWithPackageNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val symbolListWithPackageName = AGP.run { variant.symbolListWithPackageName } if (symbolListWithPackageName.isEmpty) { fail("symbolListWithPackageName is empty") @@ -461,12 +383,16 @@ class SymbolListWithPackageNameTestUnit : VariantTestCase() { } class AllClassesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val location = AGP.run { variant.allClasses }.files - assertTrue("ALL_CLASSES: $location", location::isNotEmpty) - assertTrue("No class file found at $location") { - location.search(File::isFile).isNotEmpty() + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + variant.assembleTaskProvider.configure { + it.doFirst { + val location = AGP.run { variant.allClasses }.files + assertTrue("ALL_CLASSES: $location", location::isNotEmpty) + assertTrue("No class file found at $location") { + location.search(File::isFile).isNotEmpty() + } + } } } } diff --git a/booster-android-gradle-v3_3/src/integrationTest/resources/app.gradle b/booster-android-gradle-v8_0/src/integrationTest/resources/app.gradle similarity index 93% rename from booster-android-gradle-v3_3/src/integrationTest/resources/app.gradle rename to booster-android-gradle-v8_0/src/integrationTest/resources/app.gradle index aa3c5f2d6..2d3799f8e 100644 --- a/booster-android-gradle-v3_3/src/integrationTest/resources/app.gradle +++ b/booster-android-gradle-v8_0/src/integrationTest/resources/app.gradle @@ -11,7 +11,7 @@ buildscript { classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { exclude group: 'com.google.guava' } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" + classpath "io.bootstage.testkit:testkit-gradle-plugin:2.1.0" } } @@ -20,6 +20,7 @@ apply plugin: 'com.didiglobal.booster' apply plugin: 'io.bootstage.testkit' android { + namespace 'com.didiglobal.booster.android.test' compileSdkVersion project.compile_sdk_version as Integer buildToolsVersion project.build_tools_version defaultConfig { diff --git a/booster-android-gradle-v3_5/src/integrationTest/resources/buildSrc/build.gradle b/booster-android-gradle-v8_0/src/integrationTest/resources/buildSrc/build.gradle similarity index 90% rename from booster-android-gradle-v3_5/src/integrationTest/resources/buildSrc/build.gradle rename to booster-android-gradle-v8_0/src/integrationTest/resources/buildSrc/build.gradle index 79a9b104a..d52ed4cb7 100644 --- a/booster-android-gradle-v3_5/src/integrationTest/resources/buildSrc/build.gradle +++ b/booster-android-gradle-v8_0/src/integrationTest/resources/buildSrc/build.gradle @@ -20,5 +20,5 @@ dependencies { implementation("com.didiglobal.booster:booster-android-gradle-api:${project.booster_version}") { exclude group: 'com.google.guava' } - implementation "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" + implementation "io.bootstage.testkit:testkit-gradle-plugin:2.1.0" } diff --git a/booster-android-gradle-v3_5/src/integrationTest/resources/lib.gradle b/booster-android-gradle-v8_0/src/integrationTest/resources/lib.gradle similarity index 92% rename from booster-android-gradle-v3_5/src/integrationTest/resources/lib.gradle rename to booster-android-gradle-v8_0/src/integrationTest/resources/lib.gradle index adc9b1ca0..b9ee3b136 100644 --- a/booster-android-gradle-v3_5/src/integrationTest/resources/lib.gradle +++ b/booster-android-gradle-v8_0/src/integrationTest/resources/lib.gradle @@ -11,7 +11,7 @@ buildscript { classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { exclude group: 'com.google.guava' } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" + classpath "io.bootstage.testkit:testkit-gradle-plugin:2.1.0" } } @@ -20,6 +20,7 @@ apply plugin: 'com.didiglobal.booster' apply plugin: 'io.bootstage.testkit' android { + namespace 'com.didiglobal.booster.android.test' compileSdkVersion project.compile_sdk_version as Integer buildToolsVersion project.build_tools_version defaultConfig { diff --git a/booster-android-gradle-v3_3/src/integrationTest/resources/src/main/AndroidManifest.xml b/booster-android-gradle-v8_0/src/integrationTest/resources/src/main/AndroidManifest.xml similarity index 53% rename from booster-android-gradle-v3_3/src/integrationTest/resources/src/main/AndroidManifest.xml rename to booster-android-gradle-v8_0/src/integrationTest/resources/src/main/AndroidManifest.xml index 30800c604..2969fc910 100644 --- a/booster-android-gradle-v3_3/src/integrationTest/resources/src/main/AndroidManifest.xml +++ b/booster-android-gradle-v8_0/src/integrationTest/resources/src/main/AndroidManifest.xml @@ -1,9 +1,8 @@ - + - + \ No newline at end of file diff --git a/booster-android-gradle-v3_3/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java b/booster-android-gradle-v8_0/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java similarity index 100% rename from booster-android-gradle-v3_3/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java rename to booster-android-gradle-v8_0/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java diff --git a/booster-android-gradle-v3_3/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java b/booster-android-gradle-v8_0/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java similarity index 100% rename from booster-android-gradle-v3_3/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java rename to booster-android-gradle-v8_0/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java diff --git a/booster-android-gradle-v3_3/src/integrationTest/resources/src/main/res/values/strings.xml b/booster-android-gradle-v8_0/src/integrationTest/resources/src/main/res/values/strings.xml similarity index 100% rename from booster-android-gradle-v3_3/src/integrationTest/resources/src/main/res/values/strings.xml rename to booster-android-gradle-v8_0/src/integrationTest/resources/src/main/res/values/strings.xml diff --git a/booster-android-gradle-v8_0/src/main/kotlin/com/didiglobal/booster/android/gradle/v8_0/V80.kt b/booster-android-gradle-v8_0/src/main/kotlin/com/didiglobal/booster/android/gradle/v8_0/V80.kt new file mode 100644 index 000000000..d557dd11f --- /dev/null +++ b/booster-android-gradle-v8_0/src/main/kotlin/com/didiglobal/booster/android/gradle/v8_0/V80.kt @@ -0,0 +1,333 @@ +package com.didiglobal.booster.android.gradle.v8_0 + +import com.android.build.api.artifact.Artifact +import com.android.build.api.artifact.MultipleArtifact +import com.android.build.api.artifact.SingleArtifact +import com.android.build.api.artifact.impl.ArtifactsImpl +import com.android.build.api.component.analytics.AnalyticsEnabledVariant +import com.android.build.api.variant.AndroidVersion +import com.android.build.api.variant.ApplicationVariant +import com.android.build.api.variant.LibraryVariant +import com.android.build.api.variant.Variant +import com.android.build.api.variant.impl.TaskProviderBasedDirectoryEntryImpl +import com.android.build.api.variant.impl.VariantImpl +import com.android.build.gradle.internal.api.artifact.SourceArtifactType +import com.android.build.gradle.internal.publishing.AndroidArtifacts +import com.android.build.gradle.internal.scope.BuildArtifactType +import com.android.build.gradle.internal.scope.InternalArtifactType +import com.android.build.gradle.internal.scope.InternalMultipleArtifactType +import com.android.build.gradle.internal.tasks.factory.GlobalTaskCreationConfigImpl +import com.android.build.gradle.internal.variant.BaseVariantData +import com.android.sdklib.BuildToolInfo +import com.didiglobal.booster.gradle.AGPInterface +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.artifacts.ArtifactCollection +import org.gradle.api.artifacts.component.ComponentIdentifier +import org.gradle.api.artifacts.result.ResolvedArtifactResult +import org.gradle.api.artifacts.result.ResolvedDependencyResult +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.FileCollection +import org.gradle.api.file.FileSystemLocation +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.TaskProvider +import java.io.File +import java.util.TreeMap +import kotlin.reflect.full.declaredMemberProperties +import kotlin.reflect.jvm.isAccessible + +@Suppress("UnstableApiUsage") +private val SINGLE_ARTIFACT_TYPES = arrayOf( + BuildArtifactType::class, + InternalArtifactType::class, + SingleArtifact::class, + SourceArtifactType::class +).map { + it.sealedSubclasses +}.flatten().map { + it.objectInstance as Artifact.Single +}.associateBy { + it.javaClass.simpleName +} + +private val MULTIPLE_ARTIFACT_TYPES = arrayOf( + MultipleArtifact::class, + InternalMultipleArtifactType::class +).map { + it.sealedSubclasses +}.flatten().map { + it.objectInstance as Artifact.Multiple +}.associateBy { + it.javaClass.simpleName +} + +@Suppress("DEPRECATION") +internal object V80 : AGPInterface { + + private val Variant.component: VariantImpl<*> + get() = when (this) { + is VariantImpl<*> -> this + is AnalyticsEnabledVariant -> this.delegate as VariantImpl<*> + else -> TODO("No implementationed!") + } + + @Suppress("UnstableApiUsage") + private fun Variant.getFinalArtifactFiles(type: Artifact.Single): FileCollection { + return try { + project.objects.fileCollection().from(artifactsImpl.get(type)) + } catch (e: Throwable) { + project.objects.fileCollection().builtBy(artifactsImpl.get(type)) + } + } + + @Suppress("UnstableApiUsage") + private fun Variant.getFinalArtifactFiles(type: Artifact.Multiple): FileCollection { + return try { + project.objects.fileCollection().from(artifactsImpl.getAll(type)) + } catch (e: Throwable) { + project.objects.fileCollection().builtBy(artifactsImpl.getAll(type)) + } + } + + @Suppress("UnstableApiUsage") + private val Variant.artifactsImpl: ArtifactsImpl + get() = component.artifacts + + override val Variant.project: Project + get() { + return this.component.variantDependencies.javaClass.kotlin.declaredMemberProperties.first { + it.name == "project" + }.apply { + isAccessible = true + }.get(this.component.variantDependencies) as Project + } + + override val Variant.javaCompilerTaskProvider: TaskProvider + get() = component.taskContainer.javacTask + + override val Variant.preBuildTaskProvider: TaskProvider + get() = component.taskContainer.preBuildTask + + override val Variant.assembleTaskProvider: TaskProvider + get() = component.taskContainer.assembleTask + + override val Variant.mergeAssetsTaskProvider: TaskProvider + get() = component.taskContainer.mergeAssetsTask + + override val Variant.mergeResourcesTaskProvider: TaskProvider + get() = try { + project.tasks.named(getTaskName("merge", "Resources")) + } catch (e: Throwable) { + component.taskContainer.mergeResourcesTask + } + + override val Variant.mergeNativeLibsTaskProvider: TaskProvider + get() = project.tasks.named(getTaskName("merge", "NativeLibs")) + + override val Variant.processJavaResourcesTaskProvider: TaskProvider + get() = component.taskContainer.processJavaResourcesTask + + override fun Variant.getTaskName(prefix: String): String { + return component.computeTaskName(prefix) + } + + override fun Variant.getTaskName(prefix: String, suffix: String): String { + return component.computeTaskName(prefix, suffix) + } + + override val Variant.variantData: BaseVariantData + get() = component.javaClass.getDeclaredMethod("getVariantData").apply { + isAccessible = true + }.invoke(this) as BaseVariantData + + @Suppress("DEPRECATION") + private val Variant.globalScope: GlobalTaskCreationConfigImpl + get() = component.global as GlobalTaskCreationConfigImpl + + override val Variant.originalApplicationId: String + get() = component.namespace.get() + + override val Variant.hasDynamicFeature: Boolean + get() = component.global.hasDynamicFeatures + + override val Variant.rawAndroidResources: FileCollection + get() { + val allRes: ConfigurableFileCollection = component.services.fileCollection() + + allRes.from( + component.variantDependencies.getArtifactCollection( + AndroidArtifacts.ConsumedConfigType.RUNTIME_CLASSPATH, + AndroidArtifacts.ArtifactScope.ALL, + AndroidArtifacts.ArtifactType.ANDROID_RES + ).artifactFiles + ) + + allRes.from( + component.services.fileCollection(variantData.extraGeneratedResFolders) + .builtBy(listOfNotNull(variantData.extraGeneratedResFolders.builtBy)) + ) + + component.taskContainer.generateApkDataTask?.let { + allRes.from(artifactsImpl.get(InternalArtifactType.MICRO_APK_RES)) + } + + component.sources.res { resSources -> + allRes.from( + resSources.getVariantSources().map { directoryEntries -> + directoryEntries.directoryEntries + .map { + if (it is TaskProviderBasedDirectoryEntryImpl) { + it.directoryProvider + } else { + it.asFiles( + component.services.provider { + component.services.projectInfo.projectDirectory + }) + } + } + } + ) + } + + return allRes + } + override val Variant.sourceSetMap: FileCollection + get() = getFinalArtifactFiles(InternalArtifactType.SOURCE_SET_PATH_MAP) + + override val Variant.localAndroidResources: FileCollection + get() = component.services.fileCollection().from(component.sources.res?.getLocalSources()?.values?.map { + it.map { dirs -> + dirs.map { dir -> + dir.asFileTree + }.reduce { acc, dir -> + acc.plus(dir) + } + } + }) + + override fun Variant.getSingleArtifact(type: Artifact.Single): Provider { + return artifactsImpl.get(type) + } + + override fun Variant.getArtifactCollection( + configType: AndroidArtifacts.ConsumedConfigType, + scope: AndroidArtifacts.ArtifactScope, + artifactType: AndroidArtifacts.ArtifactType + ): ArtifactCollection { + return component.variantDependencies.getArtifactCollection(configType, scope, artifactType) + } + + override fun Variant.getArtifactFileCollection( + configType: AndroidArtifacts.ConsumedConfigType, + scope: AndroidArtifacts.ArtifactScope, + artifactType: AndroidArtifacts.ArtifactType + ): FileCollection { + return component.variantDependencies.getArtifactFileCollection(configType, scope, artifactType) + } + + override val Variant.allArtifacts: Map + get() = TreeMap().also { all -> + SINGLE_ARTIFACT_TYPES.entries.associateTo(all) { (name, type) -> + val artifacts: FileCollection by lazy { + getFinalArtifactFiles(type) + } + name to artifacts + } + MULTIPLE_ARTIFACT_TYPES.entries.associateTo(all) { (name, type) -> + val artifacts: FileCollection by lazy { + getFinalArtifactFiles(type) + } + name to artifacts + } + } + + override val Variant.targetVersion: AndroidVersion + get() = targetSdkVersion + + override val Variant.isApplication: Boolean + get() = component.componentType.isApk + + override val Variant.isLibrary: Boolean + get() = component.componentType.isAar + + override val Variant.isDynamicFeature: Boolean + get() = component.componentType.isDynamicFeature + + override val Variant.aar: FileCollection + get() = getFinalArtifactFiles(SingleArtifact.AAR) + + override val Variant.apk: FileCollection + get() = getFinalArtifactFiles(SingleArtifact.APK) + + override val Variant.mergedManifests: FileCollection + get() = getFinalArtifactFiles(SingleArtifact.MERGED_MANIFEST) + + override val Variant.mergedRes: FileCollection + get() = getFinalArtifactFiles(InternalArtifactType.MERGED_RES) + + override val Variant.mergedNativeLibs: FileCollection + get() = getFinalArtifactFiles(InternalArtifactType.MERGED_NATIVE_LIBS) + + override val Variant.mergedAssets: FileCollection + get() = when (this) { + is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.COMPRESSED_ASSETS) + is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.LIBRARY_ASSETS) + else -> TODO("Unsupported variant type: $name@${javaClass.name}") + } + + override val Variant.processedRes: FileCollection + get() = getFinalArtifactFiles(InternalArtifactType.PROCESSED_RES) + + override val Variant.symbolList: FileCollection + get() = when (this) { + is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.RUNTIME_SYMBOL_LIST) + is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.COMPILE_SYMBOL_LIST) + else -> TODO("Unsupported variant type : $name@${javaClass.name}") + } + + override val Variant.symbolListWithPackageName: FileCollection + get() = getFinalArtifactFiles(InternalArtifactType.SYMBOL_LIST_WITH_PACKAGE_NAME) + + override val Variant.dataBindingDependencyArtifacts: FileCollection + get() = getFinalArtifactFiles(InternalArtifactType.DATA_BINDING_DEPENDENCY_ARTIFACTS) + + override val Variant.allClasses: FileCollection + get() = when { + isApplication -> getFinalArtifactFiles(InternalArtifactType.JAVAC) + project.files("build${File.separator}tmp${File.separator}kotlin-classes${File.separator}${name}") + isLibrary -> getFinalArtifactFiles(InternalArtifactType.AAR_MAIN_JAR) + else -> project.files() + } + + override val Variant.buildTools: BuildToolInfo + get() = globalScope.versionedSdkLoader.get().buildToolInfoProvider.get() + + override val Variant.isPrecompileDependenciesResourcesEnabled: Boolean + get() = component.androidResourcesCreationConfig?.isPrecompileDependenciesResourcesEnabled == true + + override fun Variant.getDependencies( + transitive: Boolean, + filter: (ComponentIdentifier) -> Boolean + ): Collection { + val all = getArtifactCollection( + AndroidArtifacts.ConsumedConfigType.RUNTIME_CLASSPATH, + AndroidArtifacts.ArtifactScope.ALL, + AndroidArtifacts.ArtifactType.CLASSES_JAR + ).filter { result -> + filter(result.id.componentIdentifier) + }.associateBy { + it.id.componentIdentifier.displayName + } + val result = if (!transitive) { + runtimeConfiguration.incoming.resolutionResult.root.dependencies.filterIsInstance() + .mapNotNull { + it.selected.id.displayName.takeIf { id -> id in all.keys } + }.associateWith { + all[it]!! + } + } else { + all + } + return result.values.toSet() + } + +} diff --git a/booster-android-gradle-v8_0/src/main/kotlin/com/didiglobal/booster/android/gradle/v8_0/V80Factory.kt b/booster-android-gradle-v8_0/src/main/kotlin/com/didiglobal/booster/android/gradle/v8_0/V80Factory.kt new file mode 100644 index 000000000..f0ea51117 --- /dev/null +++ b/booster-android-gradle-v8_0/src/main/kotlin/com/didiglobal/booster/android/gradle/v8_0/V80Factory.kt @@ -0,0 +1,16 @@ +package com.didiglobal.booster.android.gradle.v8_0 + +import com.android.repository.Revision +import com.didiglobal.booster.android.gradle.v8_0.V80 +import com.didiglobal.booster.gradle.AGPInterface +import com.didiglobal.booster.gradle.AGPInterfaceFactory +import com.google.auto.service.AutoService + +@AutoService(AGPInterfaceFactory::class) +class V80Factory : AGPInterfaceFactory { + + override val revision: Revision = Revision(8, 0, 0) + + override fun newAGPInterface(): AGPInterface = V80 + +} diff --git a/booster-android-gradle-v7_1/README.md b/booster-android-gradle-v8_1/README.md similarity index 66% rename from booster-android-gradle-v7_1/README.md rename to booster-android-gradle-v8_1/README.md index de13f9a1a..b1ec6588e 100644 --- a/booster-android-gradle-v7_1/README.md +++ b/booster-android-gradle-v8_1/README.md @@ -1,6 +1,6 @@ -# booster-android-gradle-v7_1 +# booster-android-gradle-v8_1 -This module is an implementation of [booster-android-gradle-api](../booster-android-gradle-api) for Android gradle plugin above 7.1 +This module is an implementation of [booster-android-gradle-api](../booster-android-gradle-api) for Android gradle plugin above 8.1 -本模块是 [booster-android-gradle-api](../booster-android-gradle-api) 针对 Android gradle plugin 7.1 以上版本的实现。 +本模块是 [booster-android-gradle-api](../booster-android-gradle-api) 针对 Android gradle plugin 8.1 以上版本的实现。 diff --git a/booster-android-gradle-v7_1/build.gradle b/booster-android-gradle-v8_1/build.gradle similarity index 77% rename from booster-android-gradle-v7_1/build.gradle rename to booster-android-gradle-v8_1/build.gradle index 226e0c330..32422ec9d 100644 --- a/booster-android-gradle-v7_1/build.gradle +++ b/booster-android-gradle-v8_1/build.gradle @@ -11,11 +11,13 @@ dependencies { compileOnly 'com.android.tools:repository:30.0.0' compileOnly 'com.android.tools:common:30.0.0' compileOnly 'com.android.tools:sdklib:30.0.0' - compileOnly 'com.android.tools.build:gradle:7.1.0' - testImplementation 'com.android.tools.build:gradle:7.1.0' + compileOnly 'com.android.tools.build:gradle-api:8.1.0' + compileOnly 'com.android.tools.build:gradle:8.1.0' + testImplementation 'com.android.tools.build:gradle:8.1.0' testImplementation 'com.android.tools:common:30.0.0' - testImplementation 'io.bootstage.testkit:testkit-gradle-plugin:1.1.0' + testImplementation 'io.bootstage.testkit:testkit-gradle-plugin:2.1.0' testImplementation project(':booster-build') + testImplementation project(':booster-android-gradle-api') } jar { diff --git a/booster-android-gradle-v7_1/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v7_1/V71IntegrationTest.kt b/booster-android-gradle-v8_1/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v8_1/V81IntegrationTest.kt similarity index 56% rename from booster-android-gradle-v7_1/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v7_1/V71IntegrationTest.kt rename to booster-android-gradle-v8_1/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v8_1/V81IntegrationTest.kt index 79a5d51d8..6ed77fe08 100644 --- a/booster-android-gradle-v7_1/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v7_1/V71IntegrationTest.kt +++ b/booster-android-gradle-v8_1/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v8_1/V81IntegrationTest.kt @@ -1,13 +1,14 @@ @file:Suppress("DEPRECATION") -package com.didiglobal.booster.android.gradle.v7_1 +package com.didiglobal.booster.android.gradle.v8_1 -import com.android.build.gradle.AppExtension -import com.android.build.gradle.BaseExtension -import com.android.build.gradle.LibraryExtension -import com.android.build.gradle.api.BaseVariant +import com.android.build.api.variant.AndroidComponentsExtension +import com.android.build.api.variant.Variant import com.didiglobal.booster.gradle.AGP -import com.didiglobal.booster.gradle.getAndroid +import com.didiglobal.booster.gradle.assembleTaskProvider +import com.didiglobal.booster.gradle.getAndroidComponents +import com.didiglobal.booster.gradle.project +import com.didiglobal.booster.kotlinx.capitalized import com.didiglobal.booster.kotlinx.search import io.bootstage.testkit.gradle.Case import io.bootstage.testkit.gradle.TestCase @@ -34,23 +35,23 @@ private val MIN_SDK_VERSION = System.getProperty("android.minsdk.version").toInt private const val TARGET_SDK_VERSION = 30 private val ARGS = System.getProperty("gradle.args").split("\\s+".toRegex()) + listOf( - "-Pbooster_version=${Build.VERSION}", - "-Pandroid_gradle_version=7.1.0", - "-Pcompile_sdk_version=30", - "-Pbuild_tools_version=29.0.2", - "-Pmin_sdk_version=${MIN_SDK_VERSION}", - "-Ptarget_sdk_version=${TARGET_SDK_VERSION}" + "-Pbooster_version=${Build.VERSION}", + "-Pandroid_gradle_version=8.1.0", + "-Pcompile_sdk_version=30", + "-Pbuild_tools_version=29.0.2", + "-Pmin_sdk_version=$MIN_SDK_VERSION", + "-Ptarget_sdk_version=$TARGET_SDK_VERSION" ) @Suppress("RemoveCurlyBracesFromTemplate", "FunctionName") -abstract class V71IntegrationTest(private val isLib: Boolean) { +abstract class V81IntegrationTest(private val isLib: Boolean) { private val projectDir = TemporaryFolder() @get:Rule val ruleChain: TestRule = rule(projectDir) { rule(LocalProperties(projectDir::getRoot)) { - GradleExecutor(projectDir::getRoot, "7.2", *ARGS.toTypedArray()) + GradleExecutor(projectDir::getRoot, "8.0", *ARGS.toTypedArray()) } } @@ -60,17 +61,10 @@ abstract class V71IntegrationTest(private val isLib: Boolean) { projectDir.copyFromResource("buildSrc") projectDir.copyFromResource("src") projectDir.newFile("gradle.properties").writeText("org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=2g") - assertEquals(7, AGP.revision.major) + assertEquals(8, AGP.revision.major) assertEquals(1, AGP.revision.minor) } - @Test - @Case(ScopeFullWithFeaturesTest::class) - fun `test AGPInterface#scopeFullWithFeatures`() = Unit - - @Test - @Case(ScopeFullLibraryWithFeaturesTest::class) - fun `test AGPInterface#scopeFullLibraryWithFeatures`() = Unit @Test @Case(ProjectTest::class) @@ -96,82 +90,6 @@ abstract class V71IntegrationTest(private val isLib: Boolean) { @Case(MergeResourcesTaskTestUnit::class) fun `test AGPInterface#mergeResources`() = Unit - @Test - @Case(GetTaskNameTestUnit::class) - fun `test AGPInterface#getTaskName(String)`() = Unit - - @Test - @Case(GetTaskName2TestUnit::class) - fun `test AGPInterface#getTaskName(String, String)`() = Unit - - @Test - @Case(VariantDataTestUnit::class) - fun `test AGPInterface#variantData`() = Unit - - @Test - @Case(OriginalApplicationIdTestUnit::class) - fun `test AGPInterface#originalApplicationId`() = Unit - - @Test - @Case(HasDynamicFeatureTestUnit::class) - fun `test AGPInterface#hasDynamicFeature`() = Unit - - @Test - @Case(RawAndroidResourcesTestUnit::class) - fun `test AGPInterface#rawAndroidResources`() = Unit - - @Test - @Case(AllArtifactsTestUnit::class) - fun `test AGPInterface#allArtifacts`() = Unit - - @Test - @Case(MinSdkVersionTestUnit::class) - fun `test AGPInterface#minSdkVersion`() = Unit - - @Test - @Case(TargetSdkVersionTestUnit::class) - fun `test AGPInterface#targetSdkVersion`() = Unit - - @Test - @Case(AarTestUnit::class) - fun `test AGPInterface#aar`() { - } - - @Test - @Case(ApkTestUnit::class) - fun `test AGPInterface#apk`() { - } - - @Test - @Case(MergedManifestsTestUnit::class) - fun `test AGPInterface#mergedManifests`() { - } - - @Test - @Case(MergedResourcesTestUnit::class) - fun `test AGPInterface#mergedRes`() { - } - - @Test - @Case(MergedAssetsTestUnit::class) - fun `test AGPInterface#mergedAssets`() { - } - - @Test - @Case(ProcessedResTestUnit::class) - fun `test AGPInterface#processedRes`() { - } - - @Test - @Case(SymbolListTestUnit::class) - fun `test AGPInterface#symbolList`() { - } - - @Test - @Case(SymbolListWithPackageNameTestUnit::class) - fun `test AGPInterface#symbolListWithPackageName`() { - } - @Test @Case(AllClassesTestUnit::class) fun `test AGPInterface#allClasses`() { @@ -179,100 +97,102 @@ abstract class V71IntegrationTest(private val isLib: Boolean) { } -class V71AppIntegrationTest : V71IntegrationTest(false) +class V81AppIntegrationTest : V81IntegrationTest(false) -class V71LibIntegrationTest : V71IntegrationTest(true) +class V81LibIntegrationTest : V81IntegrationTest(true) -class ScopeFullWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("PROJECT,SUB_PROJECTS,EXTERNAL_LIBRARIES,FEATURES", AGP.scopeFullWithFeatures.joinToString(",")) - } -} - -class ScopeFullLibraryWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("FEATURES,PROJECT", AGP.scopeFullLibraryWithFeatures.joinToString(",")) - } -} class ProjectTest : TestCase { override fun apply(project: Project) { - val assert: (BaseVariant) -> Unit = { variant -> + val assert: (Variant) -> Unit = { variant -> assertEquals(project, AGP.run { variant.project }) } - project.afterEvaluate { - when (val android = project.getAndroid()) { - is AppExtension -> android.applicationVariants.forEach(assert) - is LibraryExtension -> android.libraryVariants.forEach(assert) - } - } + project.getAndroidComponents>().onVariants(callback = assert) } } class JavaCompilerTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.javaCompilerTask }) + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + assertNotNull(AGP.run { + variant.javaCompilerTask + }) + } } } class PreBuildTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.preBuildTask }) + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + assertNotNull(AGP.run { variant.preBuildTask }) + } } } class AssembleTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.assembleTask }) + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + assertNotNull(AGP.run { variant.assembleTask }) + } } } class MergeAssetsTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeAssetsTask }) + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + assertNotNull(AGP.run { variant.mergeAssetsTask }) + } } } class MergeResourcesTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeResourcesTask }) + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + assertNotNull(AGP.run { variant.mergeResourcesTask }) + } } } class GetTaskNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("assemble${variant.name.capitalize()}", AGP.run { variant.getTaskName("assemble") }) + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + assertEquals("assemble${variant.name.capitalized()}", AGP.run { variant.getTaskName("assemble") }) + } } } class GetTaskName2TestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("merge${variant.name.capitalize()}Resources", AGP.run { variant.getTaskName("merge", "Resources") }) + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + assertEquals("merge${variant.name.capitalized()}Resources", AGP.run { variant.getTaskName("merge", "Resources") }) + } } } class VariantDataTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { + override fun apply(variant: Variant) { assertNotNull(AGP.run { variant.variantData }) } } class OriginalApplicationIdTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.originalApplicationId }) + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + assertNotNull(AGP.run { variant.originalApplicationId }) + } } } class HasDynamicFeatureTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { + override fun apply(variant: Variant) { assertFalse(AGP.run { variant.hasDynamicFeature }) } } class RawAndroidResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val rawAndroidResources = AGP.run { variant.rawAndroidResources } assertNotNull(rawAndroidResources) if (rawAndroidResources.isEmpty) { @@ -286,8 +206,8 @@ class RawAndroidResourcesTestUnit : VariantTestCase() { } class AllArtifactsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val allArtifacts = AGP.run { variant.allArtifacts } assertNotNull(allArtifacts) if (allArtifacts.isEmpty()) { @@ -301,7 +221,7 @@ class AllArtifactsTestUnit : VariantTestCase() { } class MinSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { + override fun apply(variant: Variant) { val minSdkVersion = AGP.run { variant.minSdkVersion } assertNotNull(minSdkVersion) assertEquals(MIN_SDK_VERSION, minSdkVersion.apiLevel) @@ -309,7 +229,7 @@ class MinSdkVersionTestUnit : VariantTestCase() { } class TargetSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { + override fun apply(variant: Variant) { val targetSdkVersion = AGP.run { variant.targetSdkVersion } assertNotNull(targetSdkVersion) assertEquals(TARGET_SDK_VERSION, targetSdkVersion.apiLevel) @@ -323,8 +243,8 @@ class AarTestUnit : VariantTestCase() { } } - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val aar = AGP.run { variant.aar }.search { it.extension == "aar" } @@ -345,8 +265,8 @@ class ApkTestUnit : VariantTestCase() { } } - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val apk = AGP.run { variant.apk }.search { it.extension == "apk" } @@ -367,8 +287,8 @@ class MergedManifestsTestUnit : VariantTestCase() { } } - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val mergedManifests = AGP.run { variant.mergedManifests }.search { it.name == "AndroidManifest.xml" } @@ -383,8 +303,8 @@ class MergedManifestsTestUnit : VariantTestCase() { } class MergedResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val mergedResources = AGP.run { variant.mergedRes } if (mergedResources.isEmpty) { fail("mergedRes is empty") @@ -397,10 +317,10 @@ class MergedResourcesTestUnit : VariantTestCase() { } class MergedAssetsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val mergedAssets = AGP.run { variant.mergedAssets } - if (mergedAssets.isEmpty) { + if (mergedAssets.isEmpty()) { fail("mergedAssets is empty") } mergedAssets.forEach { @@ -417,8 +337,8 @@ class ProcessedResTestUnit : VariantTestCase() { } } - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val processedRes = AGP.run { variant.processedRes }.search { it.extension == "ap_" } @@ -433,8 +353,8 @@ class ProcessedResTestUnit : VariantTestCase() { } class SymbolListTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val symbolList = AGP.run { variant.symbolList } if (symbolList.isEmpty) { fail("symbolList is empty") @@ -447,8 +367,8 @@ class SymbolListTestUnit : VariantTestCase() { } class SymbolListWithPackageNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val symbolListWithPackageName = AGP.run { variant.symbolListWithPackageName } if (symbolListWithPackageName.isEmpty) { fail("symbolListWithPackageName is empty") @@ -461,12 +381,16 @@ class SymbolListWithPackageNameTestUnit : VariantTestCase() { } class AllClassesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val location = AGP.run { variant.allClasses }.files - assertTrue("ALL_CLASSES: $location", location::isNotEmpty) - assertTrue("No class file found at $location") { - location.search(File::isFile).isNotEmpty() + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + variant.assembleTaskProvider.configure { + it.doFirst { + val location = AGP.run { variant.allClasses }.files + assertTrue("ALL_CLASSES: $location", location::isNotEmpty) + assertTrue("No class file found at $location") { + location.search(File::isFile).isNotEmpty() + } + } } } } diff --git a/booster-android-gradle-v3_5/src/integrationTest/resources/app.gradle b/booster-android-gradle-v8_1/src/integrationTest/resources/app.gradle similarity index 93% rename from booster-android-gradle-v3_5/src/integrationTest/resources/app.gradle rename to booster-android-gradle-v8_1/src/integrationTest/resources/app.gradle index aa3c5f2d6..2d3799f8e 100644 --- a/booster-android-gradle-v3_5/src/integrationTest/resources/app.gradle +++ b/booster-android-gradle-v8_1/src/integrationTest/resources/app.gradle @@ -11,7 +11,7 @@ buildscript { classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { exclude group: 'com.google.guava' } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" + classpath "io.bootstage.testkit:testkit-gradle-plugin:2.1.0" } } @@ -20,6 +20,7 @@ apply plugin: 'com.didiglobal.booster' apply plugin: 'io.bootstage.testkit' android { + namespace 'com.didiglobal.booster.android.test' compileSdkVersion project.compile_sdk_version as Integer buildToolsVersion project.build_tools_version defaultConfig { diff --git a/booster-android-gradle-v3_3/src/integrationTest/resources/buildSrc/build.gradle b/booster-android-gradle-v8_1/src/integrationTest/resources/buildSrc/build.gradle similarity index 90% rename from booster-android-gradle-v3_3/src/integrationTest/resources/buildSrc/build.gradle rename to booster-android-gradle-v8_1/src/integrationTest/resources/buildSrc/build.gradle index 79a9b104a..d52ed4cb7 100644 --- a/booster-android-gradle-v3_3/src/integrationTest/resources/buildSrc/build.gradle +++ b/booster-android-gradle-v8_1/src/integrationTest/resources/buildSrc/build.gradle @@ -20,5 +20,5 @@ dependencies { implementation("com.didiglobal.booster:booster-android-gradle-api:${project.booster_version}") { exclude group: 'com.google.guava' } - implementation "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" + implementation "io.bootstage.testkit:testkit-gradle-plugin:2.1.0" } diff --git a/booster-android-gradle-v3_3/src/integrationTest/resources/lib.gradle b/booster-android-gradle-v8_1/src/integrationTest/resources/lib.gradle similarity index 92% rename from booster-android-gradle-v3_3/src/integrationTest/resources/lib.gradle rename to booster-android-gradle-v8_1/src/integrationTest/resources/lib.gradle index adc9b1ca0..b9ee3b136 100644 --- a/booster-android-gradle-v3_3/src/integrationTest/resources/lib.gradle +++ b/booster-android-gradle-v8_1/src/integrationTest/resources/lib.gradle @@ -11,7 +11,7 @@ buildscript { classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { exclude group: 'com.google.guava' } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" + classpath "io.bootstage.testkit:testkit-gradle-plugin:2.1.0" } } @@ -20,6 +20,7 @@ apply plugin: 'com.didiglobal.booster' apply plugin: 'io.bootstage.testkit' android { + namespace 'com.didiglobal.booster.android.test' compileSdkVersion project.compile_sdk_version as Integer buildToolsVersion project.build_tools_version defaultConfig { diff --git a/booster-android-gradle-v3_4/src/integrationTest/resources/src/main/AndroidManifest.xml b/booster-android-gradle-v8_1/src/integrationTest/resources/src/main/AndroidManifest.xml similarity index 53% rename from booster-android-gradle-v3_4/src/integrationTest/resources/src/main/AndroidManifest.xml rename to booster-android-gradle-v8_1/src/integrationTest/resources/src/main/AndroidManifest.xml index 30800c604..2969fc910 100644 --- a/booster-android-gradle-v3_4/src/integrationTest/resources/src/main/AndroidManifest.xml +++ b/booster-android-gradle-v8_1/src/integrationTest/resources/src/main/AndroidManifest.xml @@ -1,9 +1,8 @@ - + - + \ No newline at end of file diff --git a/booster-android-gradle-v3_4/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java b/booster-android-gradle-v8_1/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java similarity index 100% rename from booster-android-gradle-v3_4/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java rename to booster-android-gradle-v8_1/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java diff --git a/booster-android-gradle-v3_4/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java b/booster-android-gradle-v8_1/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java similarity index 100% rename from booster-android-gradle-v3_4/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java rename to booster-android-gradle-v8_1/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java diff --git a/booster-android-gradle-v3_4/src/integrationTest/resources/src/main/res/values/strings.xml b/booster-android-gradle-v8_1/src/integrationTest/resources/src/main/res/values/strings.xml similarity index 100% rename from booster-android-gradle-v3_4/src/integrationTest/resources/src/main/res/values/strings.xml rename to booster-android-gradle-v8_1/src/integrationTest/resources/src/main/res/values/strings.xml diff --git a/booster-android-gradle-v8_1/src/main/kotlin/com/didiglobal/booster/android/gradle/v8_1/V81.kt b/booster-android-gradle-v8_1/src/main/kotlin/com/didiglobal/booster/android/gradle/v8_1/V81.kt new file mode 100644 index 000000000..ea249f13f --- /dev/null +++ b/booster-android-gradle-v8_1/src/main/kotlin/com/didiglobal/booster/android/gradle/v8_1/V81.kt @@ -0,0 +1,336 @@ +package com.didiglobal.booster.android.gradle.v8_1 + +import com.android.build.api.artifact.Artifact +import com.android.build.api.artifact.MultipleArtifact +import com.android.build.api.artifact.SingleArtifact +import com.android.build.api.artifact.impl.ArtifactsImpl +import com.android.build.api.component.analytics.AnalyticsEnabledVariant +import com.android.build.api.variant.AndroidVersion +import com.android.build.api.variant.ApplicationVariant +import com.android.build.api.variant.LibraryVariant +import com.android.build.api.variant.Variant +import com.android.build.api.variant.impl.TaskProviderBasedDirectoryEntryImpl +import com.android.build.api.variant.impl.VariantImpl +import com.android.build.gradle.internal.api.artifact.SourceArtifactType +import com.android.build.gradle.internal.publishing.AndroidArtifacts +import com.android.build.gradle.internal.scope.BuildArtifactType +import com.android.build.gradle.internal.scope.InternalArtifactType +import com.android.build.gradle.internal.scope.InternalMultipleArtifactType +import com.android.build.gradle.internal.tasks.factory.GlobalTaskCreationConfigImpl +import com.android.build.gradle.internal.variant.BaseVariantData +import com.android.sdklib.BuildToolInfo +import com.didiglobal.booster.gradle.AGPInterface +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.artifacts.ArtifactCollection +import org.gradle.api.artifacts.component.ComponentIdentifier +import org.gradle.api.artifacts.result.ResolvedArtifactResult +import org.gradle.api.artifacts.result.ResolvedDependencyResult +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.FileCollection +import org.gradle.api.file.FileSystemLocation +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.TaskProvider +import java.io.File +import java.util.TreeMap +import kotlin.reflect.full.declaredMemberProperties +import kotlin.reflect.jvm.isAccessible + +@Suppress("UnstableApiUsage") +private val SINGLE_ARTIFACT_TYPES = arrayOf( + BuildArtifactType::class, + InternalArtifactType::class, + SingleArtifact::class, + SourceArtifactType::class +).map { + it.sealedSubclasses +}.flatten().map { + it.objectInstance as Artifact.Single +}.associateBy { + it.javaClass.simpleName +} + +private val MULTIPLE_ARTIFACT_TYPES = arrayOf( + MultipleArtifact::class, + InternalMultipleArtifactType::class +).map { + it.sealedSubclasses +}.flatten().map { + it.objectInstance as Artifact.Multiple +}.associateBy { + it.javaClass.simpleName +} + +@Suppress("DEPRECATION") +internal object V81 : AGPInterface { + + private val Variant.component: VariantImpl<*> + get() = when (this) { + is VariantImpl<*> -> this + is AnalyticsEnabledVariant -> this.delegate as VariantImpl<*> + else -> TODO("No implementationed!") + } + + @Suppress("UnstableApiUsage") + private fun Variant.getFinalArtifactFiles(type: Artifact.Single): FileCollection { + return try { + project.objects.fileCollection().from(artifactsImpl.get(type)) + } catch (e: Throwable) { + project.objects.fileCollection().builtBy(artifactsImpl.get(type)) + } + } + + @Suppress("UnstableApiUsage") + private fun Variant.getFinalArtifactFiles(type: Artifact.Multiple): FileCollection { + return try { + project.objects.fileCollection().from(artifactsImpl.getAll(type)) + } catch (e: Throwable) { + project.objects.fileCollection().builtBy(artifactsImpl.getAll(type)) + } + } + + @Suppress("UnstableApiUsage") + private val Variant.artifactsImpl: ArtifactsImpl + get() = component.artifacts + + override val Variant.project: Project + get() { + return this.component.variantDependencies.javaClass.kotlin.declaredMemberProperties.first { + it.name == "project" + }.apply { + isAccessible = true + }.get(this.component.variantDependencies) as Project + } + + override val Variant.javaCompilerTaskProvider: TaskProvider + get() = component.taskContainer.javacTask + + override val Variant.preBuildTaskProvider: TaskProvider + get() = component.taskContainer.preBuildTask + + override val Variant.assembleTaskProvider: TaskProvider + get() = component.taskContainer.assembleTask + + override val Variant.mergeAssetsTaskProvider: TaskProvider + get() = component.taskContainer.mergeAssetsTask + + override val Variant.mergeResourcesTaskProvider: TaskProvider + get() = try { + project.tasks.named(getTaskName("merge", "Resources")) + } catch (e: Throwable) { + component.taskContainer.mergeResourcesTask + } + + override val Variant.mergeNativeLibsTaskProvider: TaskProvider + get() = project.tasks.named(getTaskName("merge", "NativeLibs")) + + override val Variant.processJavaResourcesTaskProvider: TaskProvider + get() = component.taskContainer.processJavaResourcesTask + + override fun Variant.getTaskName(prefix: String): String { + return component.computeTaskName(prefix) + } + + override fun Variant.getTaskName(prefix: String, suffix: String): String { + return component.computeTaskName(prefix, suffix) + } + + override val Variant.variantData: BaseVariantData + get() = component.javaClass.getDeclaredMethod("getVariantData").apply { + isAccessible = true + }.invoke(this) as BaseVariantData + + @Suppress("DEPRECATION") + private val Variant.globalScope: GlobalTaskCreationConfigImpl + get() = component.global as GlobalTaskCreationConfigImpl + + override val Variant.originalApplicationId: String + get() = component.namespace.get() + + override val Variant.hasDynamicFeature: Boolean + get() = component.global.hasDynamicFeatures + + override val Variant.rawAndroidResources: FileCollection + get() { + val allRes: ConfigurableFileCollection = component.services.fileCollection() + + allRes.from( + component.variantDependencies.getArtifactCollection( + AndroidArtifacts.ConsumedConfigType.RUNTIME_CLASSPATH, + AndroidArtifacts.ArtifactScope.ALL, + AndroidArtifacts.ArtifactType.ANDROID_RES + ).artifactFiles + ) + + allRes.from( + component.services.fileCollection(variantData.extraGeneratedResFolders) + .builtBy(listOfNotNull(variantData.extraGeneratedResFolders.builtBy)) + ) + + component.taskContainer.generateApkDataTask?.let { + allRes.from(artifactsImpl.get(InternalArtifactType.MICRO_APK_RES)) + } + + component.sources.res { resSources -> + allRes.from( + resSources.getVariantSources().map { directoryEntries -> + directoryEntries.directoryEntries + .map { + if (it is TaskProviderBasedDirectoryEntryImpl) { + it.directoryProvider + } else { + it.asFiles( + component.services.provider { + component.services.projectInfo.projectDirectory + }) + } + } + } + ) + } + + return allRes + } + override val Variant.sourceSetMap: FileCollection + get() = getFinalArtifactFiles(InternalArtifactType.SOURCE_SET_PATH_MAP) + + override val Variant.localAndroidResources: FileCollection + get() = component.services.fileCollection() + .from(component.sources.res?.getVariantSourcesWithFilter { + !it.isUserAdded && !it.isGenerated + }?.values?.map { + it.map { dirs -> + dirs.map { dir -> + dir.asFileTree + }.reduce { acc, dir -> + acc.plus(dir) + } + } + }) + + override fun Variant.getSingleArtifact(type: Artifact.Single): Provider { + return artifactsImpl.get(type) + } + + override fun Variant.getArtifactCollection( + configType: AndroidArtifacts.ConsumedConfigType, + scope: AndroidArtifacts.ArtifactScope, + artifactType: AndroidArtifacts.ArtifactType + ): ArtifactCollection { + return component.variantDependencies.getArtifactCollection(configType, scope, artifactType) + } + + override fun Variant.getArtifactFileCollection( + configType: AndroidArtifacts.ConsumedConfigType, + scope: AndroidArtifacts.ArtifactScope, + artifactType: AndroidArtifacts.ArtifactType + ): FileCollection { + return component.variantDependencies.getArtifactFileCollection(configType, scope, artifactType) + } + + override val Variant.allArtifacts: Map + get() = TreeMap().also { all -> + SINGLE_ARTIFACT_TYPES.entries.associateTo(all) { (name, type) -> + val artifacts: FileCollection by lazy { + getFinalArtifactFiles(type) + } + name to artifacts + } + MULTIPLE_ARTIFACT_TYPES.entries.associateTo(all) { (name, type) -> + val artifacts: FileCollection by lazy { + getFinalArtifactFiles(type) + } + name to artifacts + } + } + + override val Variant.targetVersion: AndroidVersion + get() = targetSdkVersion + + override val Variant.isApplication: Boolean + get() = component.componentType.isApk + + override val Variant.isLibrary: Boolean + get() = component.componentType.isAar + + override val Variant.isDynamicFeature: Boolean + get() = component.componentType.isDynamicFeature + + override val Variant.aar: FileCollection + get() = getFinalArtifactFiles(SingleArtifact.AAR) + + override val Variant.apk: FileCollection + get() = getFinalArtifactFiles(SingleArtifact.APK) + + override val Variant.mergedManifests: FileCollection + get() = getFinalArtifactFiles(SingleArtifact.MERGED_MANIFEST) + + override val Variant.mergedRes: FileCollection + get() = getFinalArtifactFiles(InternalArtifactType.MERGED_RES) + + override val Variant.mergedNativeLibs: FileCollection + get() = getFinalArtifactFiles(SingleArtifact.MERGED_NATIVE_LIBS) + + override val Variant.mergedAssets: FileCollection + get() = when (this) { + is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.COMPRESSED_ASSETS) + is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.LIBRARY_ASSETS) + else -> TODO("Unsupported variant type: $name@${javaClass.name}") + } + + override val Variant.processedRes: FileCollection + get() = getFinalArtifactFiles(InternalArtifactType.PROCESSED_RES) + + override val Variant.symbolList: FileCollection + get() = when (this) { + is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.RUNTIME_SYMBOL_LIST) + is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.COMPILE_SYMBOL_LIST) + else -> TODO("Unsupported variant type: $name@${javaClass.name}") + } + + override val Variant.symbolListWithPackageName: FileCollection + get() = getFinalArtifactFiles(InternalArtifactType.SYMBOL_LIST_WITH_PACKAGE_NAME) + + override val Variant.dataBindingDependencyArtifacts: FileCollection + get() = getFinalArtifactFiles(InternalArtifactType.DATA_BINDING_DEPENDENCY_ARTIFACTS) + + override val Variant.allClasses: FileCollection + get() = when { + isApplication -> getFinalArtifactFiles(InternalArtifactType.JAVAC) + project.files("build${File.separator}tmp${File.separator}kotlin-classes${File.separator}${name}") + isLibrary -> getFinalArtifactFiles(InternalArtifactType.AAR_MAIN_JAR) + else -> project.files() + } + + override val Variant.buildTools: BuildToolInfo + get() = globalScope.versionedSdkLoader.get().buildToolInfoProvider.get() + + override val Variant.isPrecompileDependenciesResourcesEnabled: Boolean + get() = component.androidResourcesCreationConfig?.isPrecompileDependenciesResourcesEnabled == true + + override fun Variant.getDependencies( + transitive: Boolean, + filter: (ComponentIdentifier) -> Boolean + ): Collection { + val all = getArtifactCollection( + AndroidArtifacts.ConsumedConfigType.RUNTIME_CLASSPATH, + AndroidArtifacts.ArtifactScope.ALL, + AndroidArtifacts.ArtifactType.CLASSES_JAR + ).filter { result -> + filter(result.id.componentIdentifier) + }.associateBy { + it.id.componentIdentifier.displayName + } + val result = if (!transitive) { + runtimeConfiguration.incoming.resolutionResult.root.dependencies.filterIsInstance() + .mapNotNull { + it.selected.id.displayName.takeIf { id -> id in all.keys } + }.associateWith { + all[it]!! + } + } else { + all + } + return result.values.toSet() + } + +} diff --git a/booster-android-gradle-v3_4/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_4/V34Factory.kt b/booster-android-gradle-v8_1/src/main/kotlin/com/didiglobal/booster/android/gradle/v8_1/V81Factory.kt similarity index 53% rename from booster-android-gradle-v3_4/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_4/V34Factory.kt rename to booster-android-gradle-v8_1/src/main/kotlin/com/didiglobal/booster/android/gradle/v8_1/V81Factory.kt index bbf13d377..9417d7928 100644 --- a/booster-android-gradle-v3_4/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_4/V34Factory.kt +++ b/booster-android-gradle-v8_1/src/main/kotlin/com/didiglobal/booster/android/gradle/v8_1/V81Factory.kt @@ -1,4 +1,4 @@ -package com.didiglobal.booster.android.gradle.v3_4 +package com.didiglobal.booster.android.gradle.v8_1 import com.android.repository.Revision import com.didiglobal.booster.gradle.AGPInterface @@ -6,10 +6,10 @@ import com.didiglobal.booster.gradle.AGPInterfaceFactory import com.google.auto.service.AutoService @AutoService(AGPInterfaceFactory::class) -class V34Factory : AGPInterfaceFactory { +class V81Factory : AGPInterfaceFactory { - override val revision: Revision = Revision(3, 4, 0) + override val revision: Revision = Revision(8, 1, 0) - override fun newAGPInterface(): AGPInterface = V34 + override fun newAGPInterface(): AGPInterface = V81 } diff --git a/booster-android-gradle-v7_2/README.md b/booster-android-gradle-v8_2/README.md similarity index 66% rename from booster-android-gradle-v7_2/README.md rename to booster-android-gradle-v8_2/README.md index 0ffc8d2f1..f9491fc6a 100644 --- a/booster-android-gradle-v7_2/README.md +++ b/booster-android-gradle-v8_2/README.md @@ -1,6 +1,6 @@ -# booster-android-gradle-v7_2 +# booster-android-gradle-v8_1 -This module is an implementation of [booster-android-gradle-api](../booster-android-gradle-api) for Android gradle plugin above 7.2 +This module is an implementation of [booster-android-gradle-api](../booster-android-gradle-api) for Android gradle plugin above 8.2 -本模块是 [booster-android-gradle-api](../booster-android-gradle-api) 针对 Android gradle plugin 7.2 以上版本的实现。 +本模块是 [booster-android-gradle-api](../booster-android-gradle-api) 针对 Android gradle plugin 8.2 以上版本的实现。 diff --git a/booster-android-gradle-v7_2/build.gradle b/booster-android-gradle-v8_2/build.gradle similarity index 77% rename from booster-android-gradle-v7_2/build.gradle rename to booster-android-gradle-v8_2/build.gradle index cbadd52a3..27b38b630 100644 --- a/booster-android-gradle-v7_2/build.gradle +++ b/booster-android-gradle-v8_2/build.gradle @@ -11,11 +11,13 @@ dependencies { compileOnly 'com.android.tools:repository:30.0.0' compileOnly 'com.android.tools:common:30.0.0' compileOnly 'com.android.tools:sdklib:30.0.0' - compileOnly 'com.android.tools.build:gradle:7.2.0' - testImplementation 'com.android.tools.build:gradle:7.2.0' + compileOnly 'com.android.tools.build:gradle-api:8.2.0' + compileOnly 'com.android.tools.build:gradle:8.2.0' + testImplementation 'com.android.tools.build:gradle:8.2.0' testImplementation 'com.android.tools:common:30.0.0' - testImplementation 'io.bootstage.testkit:testkit-gradle-plugin:1.1.0' + testImplementation 'io.bootstage.testkit:testkit-gradle-plugin:2.1.0' testImplementation project(':booster-build') + testImplementation project(':booster-android-gradle-api') } jar { diff --git a/booster-android-gradle-v7_3/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v7_3/V73IntegrationTest.kt b/booster-android-gradle-v8_2/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v8_2/V82IntegrationTest.kt similarity index 54% rename from booster-android-gradle-v7_3/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v7_3/V73IntegrationTest.kt rename to booster-android-gradle-v8_2/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v8_2/V82IntegrationTest.kt index 5d8e93aed..89a49911f 100644 --- a/booster-android-gradle-v7_3/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v7_3/V73IntegrationTest.kt +++ b/booster-android-gradle-v8_2/src/integrationTest/kotlin/com/didiglobal/booster/android/gradle/v8_2/V82IntegrationTest.kt @@ -1,13 +1,14 @@ @file:Suppress("DEPRECATION") -package com.didiglobal.booster.android.gradle.v7_3 +package com.didiglobal.booster.android.gradle.v8_2 -import com.android.build.gradle.AppExtension -import com.android.build.gradle.BaseExtension -import com.android.build.gradle.LibraryExtension -import com.android.build.gradle.api.BaseVariant +import com.android.build.api.variant.AndroidComponentsExtension +import com.android.build.api.variant.Variant import com.didiglobal.booster.gradle.AGP -import com.didiglobal.booster.gradle.getAndroid +import com.didiglobal.booster.gradle.assembleTaskProvider +import com.didiglobal.booster.gradle.getAndroidComponents +import com.didiglobal.booster.gradle.project +import com.didiglobal.booster.kotlinx.capitalized import com.didiglobal.booster.kotlinx.search import io.bootstage.testkit.gradle.Case import io.bootstage.testkit.gradle.TestCase @@ -22,35 +23,30 @@ import org.junit.Rule import org.junit.rules.TemporaryFolder import org.junit.rules.TestRule import java.io.File -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertNotNull -import kotlin.test.assertTrue -import kotlin.test.fail +import kotlin.test.* private val MIN_SDK_VERSION = System.getProperty("android.minsdk.version").toInt() private const val TARGET_SDK_VERSION = 30 private val ARGS = System.getProperty("gradle.args").split("\\s+".toRegex()) + listOf( - "-Pbooster_version=${Build.VERSION}", - "-Pandroid_gradle_version=7.3.0", - "-Pcompile_sdk_version=30", - "-Pbuild_tools_version=29.0.2", - "-Pmin_sdk_version=${MIN_SDK_VERSION}", - "-Ptarget_sdk_version=${TARGET_SDK_VERSION}" + "-Pbooster_version=${Build.VERSION}", + "-Pandroid_gradle_version=8.2.0", + "-Pcompile_sdk_version=30", + "-Pbuild_tools_version=29.0.2", + "-Pmin_sdk_version=$MIN_SDK_VERSION", + "-Ptarget_sdk_version=$TARGET_SDK_VERSION" ) @Suppress("RemoveCurlyBracesFromTemplate", "FunctionName") -abstract class V73IntegrationTest(private val isLib: Boolean) { +abstract class V82IntegrationTest(private val isLib: Boolean) { private val projectDir = TemporaryFolder() @get:Rule val ruleChain: TestRule = rule(projectDir) { rule(LocalProperties(projectDir::getRoot)) { - GradleExecutor(projectDir::getRoot, "7.4", *ARGS.toTypedArray()) + GradleExecutor(projectDir::getRoot, "8.2", *ARGS.toTypedArray()) } } @@ -60,17 +56,10 @@ abstract class V73IntegrationTest(private val isLib: Boolean) { projectDir.copyFromResource("buildSrc") projectDir.copyFromResource("src") projectDir.newFile("gradle.properties").writeText("org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=2g") - assertEquals(7, AGP.revision.major) - assertEquals(3, AGP.revision.minor) + assertEquals(8, AGP.revision.major) + assertEquals(2, AGP.revision.minor) } - @Test - @Case(ScopeFullWithFeaturesTest::class) - fun `test AGPInterface#scopeFullWithFeatures`() = Unit - - @Test - @Case(ScopeFullLibraryWithFeaturesTest::class) - fun `test AGPInterface#scopeFullLibraryWithFeatures`() = Unit @Test @Case(ProjectTest::class) @@ -96,193 +85,112 @@ abstract class V73IntegrationTest(private val isLib: Boolean) { @Case(MergeResourcesTaskTestUnit::class) fun `test AGPInterface#mergeResources`() = Unit - @Test - @Case(GetTaskNameTestUnit::class) - fun `test AGPInterface#getTaskName(String)`() = Unit - - @Test - @Case(GetTaskName2TestUnit::class) - fun `test AGPInterface#getTaskName(String, String)`() = Unit - - @Test - @Case(VariantDataTestUnit::class) - fun `test AGPInterface#variantData`() = Unit - - @Test - @Case(OriginalApplicationIdTestUnit::class) - fun `test AGPInterface#originalApplicationId`() = Unit - - @Test - @Case(HasDynamicFeatureTestUnit::class) - fun `test AGPInterface#hasDynamicFeature`() = Unit - - @Test - @Case(RawAndroidResourcesTestUnit::class) - fun `test AGPInterface#rawAndroidResources`() = Unit - - @Test - @Case(AllArtifactsTestUnit::class) - fun `test AGPInterface#allArtifacts`() = Unit - - @Test - @Case(MinSdkVersionTestUnit::class) - fun `test AGPInterface#minSdkVersion`() = Unit - - @Test - @Case(TargetSdkVersionTestUnit::class) - fun `test AGPInterface#targetSdkVersion`() = Unit - - @Test - @Case(AarTestUnit::class) - fun `test AGPInterface#aar`() { - } - - @Test - @Case(ApkTestUnit::class) - fun `test AGPInterface#apk`() { - } - - @Test - @Case(MergedManifestsTestUnit::class) - fun `test AGPInterface#mergedManifests`() { - } - - @Test - @Case(MergedResourcesTestUnit::class) - fun `test AGPInterface#mergedRes`() { - } - - @Test - @Case(MergedAssetsTestUnit::class) - fun `test AGPInterface#mergedAssets`() { - } - - @Test - @Case(ProcessedResTestUnit::class) - fun `test AGPInterface#processedRes`() { - } - - @Test - @Case(SymbolListTestUnit::class) - fun `test AGPInterface#symbolList`() { - } - - @Test - @Case(SymbolListWithPackageNameTestUnit::class) - fun `test AGPInterface#symbolListWithPackageName`() { - } - @Test @Case(AllClassesTestUnit::class) fun `test AGPInterface#allClasses`() { } -// @Test -// @Case(BuildToolsTestUnit::class) -// fun `test AGPInterface#buildTools`() { -// } - } -class V73AppIntegrationTest : V73IntegrationTest(false) +class V82AppIntegrationTest : V82IntegrationTest(false) -class V73LibIntegrationTest : V73IntegrationTest(true) +class V82LibIntegrationTest : V82IntegrationTest(true) -class ScopeFullWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("PROJECT,SUB_PROJECTS,EXTERNAL_LIBRARIES,FEATURES", AGP.scopeFullWithFeatures.joinToString(",")) - } -} - -class ScopeFullLibraryWithFeaturesTest : TestCase { - override fun apply(project: Project) { - assertEquals("FEATURES,PROJECT", AGP.scopeFullLibraryWithFeatures.joinToString(",")) - } -} class ProjectTest : TestCase { override fun apply(project: Project) { - val assert: (BaseVariant) -> Unit = { variant -> + val assert: (Variant) -> Unit = { variant -> assertEquals(project, AGP.run { variant.project }) } - project.afterEvaluate { - when (val android = project.getAndroid()) { - is AppExtension -> android.applicationVariants.forEach(assert) - is LibraryExtension -> android.libraryVariants.forEach(assert) - } - } + project.getAndroidComponents>().onVariants(callback = assert) } } class JavaCompilerTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.javaCompilerTask }) + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + assertNotNull(AGP.run { + variant.javaCompilerTask + }) + } } } class PreBuildTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.preBuildTask }) + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + assertNotNull(AGP.run { variant.preBuildTask }) + } } } class AssembleTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.assembleTask }) + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + assertNotNull(AGP.run { variant.assembleTask }) + } } } class MergeAssetsTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeAssetsTask }) + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + assertNotNull(AGP.run { variant.mergeAssetsTask }) + } } } class MergeResourcesTaskTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertNotNull(AGP.run { variant.mergeResourcesTask }) + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + assertNotNull(AGP.run { variant.mergeResourcesTask }) + } } } class GetTaskNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("assemble${variant.name.capitalize()}", AGP.run { variant.getTaskName("assemble") }) + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + assertEquals("assemble${variant.name.capitalized()}", AGP.run { variant.getTaskName("assemble") }) + } } } class GetTaskName2TestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - assertEquals("merge${variant.name.capitalize()}Resources", AGP.run { variant.getTaskName("merge", "Resources") }) + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + assertEquals("merge${variant.name.capitalized()}Resources", AGP.run { variant.getTaskName("merge", "Resources") }) + } } } class VariantDataTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { + override fun apply(variant: Variant) { assertNotNull(AGP.run { variant.variantData }) } } class OriginalApplicationIdTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { assertNotNull(AGP.run { variant.originalApplicationId }) } } } class HasDynamicFeatureTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { + override fun apply(variant: Variant) { assertFalse(AGP.run { variant.hasDynamicFeature }) } } class RawAndroidResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val rawAndroidResources = AGP.run { variant.rawAndroidResources } assertNotNull(rawAndroidResources) - if (rawAndroidResources.isEmpty()) { + if (rawAndroidResources.isEmpty) { fail("rawAndroidResources is empty") } rawAndroidResources.forEach { @@ -293,8 +201,8 @@ class RawAndroidResourcesTestUnit : VariantTestCase() { } class AllArtifactsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val allArtifacts = AGP.run { variant.allArtifacts } assertNotNull(allArtifacts) if (allArtifacts.isEmpty()) { @@ -308,7 +216,7 @@ class AllArtifactsTestUnit : VariantTestCase() { } class MinSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { + override fun apply(variant: Variant) { val minSdkVersion = AGP.run { variant.minSdkVersion } assertNotNull(minSdkVersion) assertEquals(MIN_SDK_VERSION, minSdkVersion.apiLevel) @@ -316,7 +224,7 @@ class MinSdkVersionTestUnit : VariantTestCase() { } class TargetSdkVersionTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { + override fun apply(variant: Variant) { val targetSdkVersion = AGP.run { variant.targetSdkVersion } assertNotNull(targetSdkVersion) assertEquals(TARGET_SDK_VERSION, targetSdkVersion.apiLevel) @@ -330,8 +238,8 @@ class AarTestUnit : VariantTestCase() { } } - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val aar = AGP.run { variant.aar }.search { it.extension == "aar" } @@ -352,8 +260,8 @@ class ApkTestUnit : VariantTestCase() { } } - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val apk = AGP.run { variant.apk }.search { it.extension == "apk" } @@ -374,8 +282,8 @@ class MergedManifestsTestUnit : VariantTestCase() { } } - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val mergedManifests = AGP.run { variant.mergedManifests }.search { it.name == "AndroidManifest.xml" } @@ -390,10 +298,10 @@ class MergedManifestsTestUnit : VariantTestCase() { } class MergedResourcesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val mergedResources = AGP.run { variant.mergedRes } - if (mergedResources.isEmpty()) { + if (mergedResources.isEmpty) { fail("mergedRes is empty") } mergedResources.forEach { @@ -404,8 +312,8 @@ class MergedResourcesTestUnit : VariantTestCase() { } class MergedAssetsTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val mergedAssets = AGP.run { variant.mergedAssets } if (mergedAssets.isEmpty()) { fail("mergedAssets is empty") @@ -424,8 +332,8 @@ class ProcessedResTestUnit : VariantTestCase() { } } - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val processedRes = AGP.run { variant.processedRes }.search { it.extension == "ap_" } @@ -440,10 +348,10 @@ class ProcessedResTestUnit : VariantTestCase() { } class SymbolListTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val symbolList = AGP.run { variant.symbolList } - if (symbolList.isEmpty()) { + if (symbolList.isEmpty) { fail("symbolList is empty") } symbolList.forEach { @@ -454,10 +362,10 @@ class SymbolListTestUnit : VariantTestCase() { } class SymbolListWithPackageNameTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { val symbolListWithPackageName = AGP.run { variant.symbolListWithPackageName } - if (symbolListWithPackageName.isEmpty()) { + if (symbolListWithPackageName.isEmpty) { fail("symbolListWithPackageName is empty") } symbolListWithPackageName.forEach { @@ -468,12 +376,16 @@ class SymbolListWithPackageNameTestUnit : VariantTestCase() { } class AllClassesTestUnit : VariantTestCase() { - override fun apply(variant: BaseVariant) { - AGP.run { variant.assembleTask }.doFirst { - val location = AGP.run { variant.allClasses }.files - assertTrue("ALL_CLASSES: $location", location::isNotEmpty) - assertTrue("No class file found at $location") { - location.search(File::isFile).isNotEmpty() + override fun apply(variant: Variant) { + variant.project.gradle.taskGraph.whenReady { + variant.assembleTaskProvider.configure { + it.doFirst { + val location = AGP.run { variant.allClasses }.files + assertTrue("ALL_CLASSES: $location", location::isNotEmpty) + assertTrue("No class file found at $location") { + location.search(File::isFile).isNotEmpty() + } + } } } } diff --git a/booster-android-gradle-v3_6/src/integrationTest/resources/app.gradle b/booster-android-gradle-v8_2/src/integrationTest/resources/app.gradle similarity index 93% rename from booster-android-gradle-v3_6/src/integrationTest/resources/app.gradle rename to booster-android-gradle-v8_2/src/integrationTest/resources/app.gradle index aa3c5f2d6..2d3799f8e 100644 --- a/booster-android-gradle-v3_6/src/integrationTest/resources/app.gradle +++ b/booster-android-gradle-v8_2/src/integrationTest/resources/app.gradle @@ -11,7 +11,7 @@ buildscript { classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { exclude group: 'com.google.guava' } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" + classpath "io.bootstage.testkit:testkit-gradle-plugin:2.1.0" } } @@ -20,6 +20,7 @@ apply plugin: 'com.didiglobal.booster' apply plugin: 'io.bootstage.testkit' android { + namespace 'com.didiglobal.booster.android.test' compileSdkVersion project.compile_sdk_version as Integer buildToolsVersion project.build_tools_version defaultConfig { diff --git a/booster-android-gradle-v3_6/src/integrationTest/resources/buildSrc/build.gradle b/booster-android-gradle-v8_2/src/integrationTest/resources/buildSrc/build.gradle similarity index 90% rename from booster-android-gradle-v3_6/src/integrationTest/resources/buildSrc/build.gradle rename to booster-android-gradle-v8_2/src/integrationTest/resources/buildSrc/build.gradle index 79a9b104a..d52ed4cb7 100644 --- a/booster-android-gradle-v3_6/src/integrationTest/resources/buildSrc/build.gradle +++ b/booster-android-gradle-v8_2/src/integrationTest/resources/buildSrc/build.gradle @@ -20,5 +20,5 @@ dependencies { implementation("com.didiglobal.booster:booster-android-gradle-api:${project.booster_version}") { exclude group: 'com.google.guava' } - implementation "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" + implementation "io.bootstage.testkit:testkit-gradle-plugin:2.1.0" } diff --git a/booster-android-gradle-v3_4/src/integrationTest/resources/lib.gradle b/booster-android-gradle-v8_2/src/integrationTest/resources/lib.gradle similarity index 92% rename from booster-android-gradle-v3_4/src/integrationTest/resources/lib.gradle rename to booster-android-gradle-v8_2/src/integrationTest/resources/lib.gradle index adc9b1ca0..b9ee3b136 100644 --- a/booster-android-gradle-v3_4/src/integrationTest/resources/lib.gradle +++ b/booster-android-gradle-v8_2/src/integrationTest/resources/lib.gradle @@ -11,7 +11,7 @@ buildscript { classpath("com.didiglobal.booster:booster-gradle-plugin:${project.booster_version}") { exclude group: 'com.google.guava' } - classpath "io.bootstage.testkit:testkit-gradle-plugin:1.4.0" + classpath "io.bootstage.testkit:testkit-gradle-plugin:2.1.0" } } @@ -20,6 +20,7 @@ apply plugin: 'com.didiglobal.booster' apply plugin: 'io.bootstage.testkit' android { + namespace 'com.didiglobal.booster.android.test' compileSdkVersion project.compile_sdk_version as Integer buildToolsVersion project.build_tools_version defaultConfig { diff --git a/booster-android-gradle-v3_5/src/integrationTest/resources/src/main/AndroidManifest.xml b/booster-android-gradle-v8_2/src/integrationTest/resources/src/main/AndroidManifest.xml similarity index 53% rename from booster-android-gradle-v3_5/src/integrationTest/resources/src/main/AndroidManifest.xml rename to booster-android-gradle-v8_2/src/integrationTest/resources/src/main/AndroidManifest.xml index 30800c604..2969fc910 100644 --- a/booster-android-gradle-v3_5/src/integrationTest/resources/src/main/AndroidManifest.xml +++ b/booster-android-gradle-v8_2/src/integrationTest/resources/src/main/AndroidManifest.xml @@ -1,9 +1,8 @@ - + - + \ No newline at end of file diff --git a/booster-android-gradle-v3_5/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java b/booster-android-gradle-v8_2/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java similarity index 100% rename from booster-android-gradle-v3_5/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java rename to booster-android-gradle-v8_2/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/MainActivity.java diff --git a/booster-android-gradle-v3_5/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java b/booster-android-gradle-v8_2/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java similarity index 100% rename from booster-android-gradle-v3_5/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java rename to booster-android-gradle-v8_2/src/integrationTest/resources/src/main/java/com/didiglobal/booster/android/test/TestApplication.java diff --git a/booster-android-gradle-v3_5/src/integrationTest/resources/src/main/res/values/strings.xml b/booster-android-gradle-v8_2/src/integrationTest/resources/src/main/res/values/strings.xml similarity index 100% rename from booster-android-gradle-v3_5/src/integrationTest/resources/src/main/res/values/strings.xml rename to booster-android-gradle-v8_2/src/integrationTest/resources/src/main/res/values/strings.xml diff --git a/booster-android-gradle-v8_2/src/main/kotlin/com/didiglobal/booster/android/gradle/v8_2/V82.kt b/booster-android-gradle-v8_2/src/main/kotlin/com/didiglobal/booster/android/gradle/v8_2/V82.kt new file mode 100644 index 000000000..3cf05945c --- /dev/null +++ b/booster-android-gradle-v8_2/src/main/kotlin/com/didiglobal/booster/android/gradle/v8_2/V82.kt @@ -0,0 +1,336 @@ +package com.didiglobal.booster.android.gradle.v8_2 + +import com.android.build.api.artifact.Artifact +import com.android.build.api.artifact.MultipleArtifact +import com.android.build.api.artifact.SingleArtifact +import com.android.build.api.artifact.impl.ArtifactsImpl +import com.android.build.api.component.analytics.AnalyticsEnabledVariant +import com.android.build.api.variant.AndroidVersion +import com.android.build.api.variant.ApplicationVariant +import com.android.build.api.variant.LibraryVariant +import com.android.build.api.variant.Variant +import com.android.build.api.variant.impl.TaskProviderBasedDirectoryEntryImpl +import com.android.build.api.variant.impl.VariantImpl +import com.android.build.gradle.internal.api.artifact.SourceArtifactType +import com.android.build.gradle.internal.publishing.AndroidArtifacts +import com.android.build.gradle.internal.scope.BuildArtifactType +import com.android.build.gradle.internal.scope.InternalArtifactType +import com.android.build.gradle.internal.scope.InternalMultipleArtifactType +import com.android.build.gradle.internal.tasks.factory.GlobalTaskCreationConfigImpl +import com.android.build.gradle.internal.variant.BaseVariantData +import com.android.sdklib.BuildToolInfo +import com.didiglobal.booster.gradle.AGPInterface +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.artifacts.ArtifactCollection +import org.gradle.api.artifacts.component.ComponentIdentifier +import org.gradle.api.artifacts.result.ResolvedArtifactResult +import org.gradle.api.artifacts.result.ResolvedDependencyResult +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.FileCollection +import org.gradle.api.file.FileSystemLocation +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.TaskProvider +import java.io.File +import java.util.TreeMap +import kotlin.reflect.full.declaredMemberProperties +import kotlin.reflect.jvm.isAccessible + +@Suppress("UnstableApiUsage") +private val SINGLE_ARTIFACT_TYPES = arrayOf( + BuildArtifactType::class, + InternalArtifactType::class, + SingleArtifact::class, + SourceArtifactType::class +).map { + it.sealedSubclasses +}.flatten().map { + it.objectInstance as Artifact.Single +}.associateBy { + it.javaClass.simpleName +} + +private val MULTIPLE_ARTIFACT_TYPES = arrayOf( + MultipleArtifact::class, + InternalMultipleArtifactType::class +).map { + it.sealedSubclasses +}.flatten().map { + it.objectInstance as Artifact.Multiple +}.associateBy { + it.javaClass.simpleName +} + +@Suppress("DEPRECATION") +internal object V82 : AGPInterface { + + private val Variant.component: VariantImpl<*> + get() = when (this) { + is VariantImpl<*> -> this + is AnalyticsEnabledVariant -> this.delegate as VariantImpl<*> + else -> TODO("No implementationed!") + } + + @Suppress("UnstableApiUsage") + private fun Variant.getFinalArtifactFiles(type: Artifact.Single): FileCollection { + return try { + project.objects.fileCollection().from(artifactsImpl.get(type)) + } catch (e: Throwable) { + project.objects.fileCollection().builtBy(artifactsImpl.get(type)) + } + } + + @Suppress("UnstableApiUsage") + private fun Variant.getFinalArtifactFiles(type: Artifact.Multiple): FileCollection { + return try { + project.objects.fileCollection().from(artifactsImpl.getAll(type)) + } catch (e: Throwable) { + project.objects.fileCollection().builtBy(artifactsImpl.getAll(type)) + } + } + + @Suppress("UnstableApiUsage") + private val Variant.artifactsImpl: ArtifactsImpl + get() = component.artifacts + + override val Variant.project: Project + get() { + return this.component.variantDependencies.javaClass.kotlin.declaredMemberProperties.first { + it.name == "project" + }.apply { + isAccessible = true + }.get(this.component.variantDependencies) as Project + } + + override val Variant.javaCompilerTaskProvider: TaskProvider + get() = component.taskContainer.javacTask + + override val Variant.preBuildTaskProvider: TaskProvider + get() = component.taskContainer.preBuildTask + + override val Variant.assembleTaskProvider: TaskProvider + get() = component.taskContainer.assembleTask + + override val Variant.mergeAssetsTaskProvider: TaskProvider + get() = component.taskContainer.mergeAssetsTask + + override val Variant.mergeResourcesTaskProvider: TaskProvider + get() = try { + project.tasks.named(getTaskName("merge", "Resources")) + } catch (e: Throwable) { + component.taskContainer.mergeResourcesTask + } + + override val Variant.mergeNativeLibsTaskProvider: TaskProvider + get() = project.tasks.named(getTaskName("merge", "NativeLibs")) + + override val Variant.processJavaResourcesTaskProvider: TaskProvider + get() = component.taskContainer.processJavaResourcesTask + + override fun Variant.getTaskName(prefix: String): String { + return component.computeTaskName(prefix) + } + + override fun Variant.getTaskName(prefix: String, suffix: String): String { + return component.computeTaskName(prefix, suffix) + } + + override val Variant.variantData: BaseVariantData + get() = component.javaClass.getDeclaredMethod("getVariantData").apply { + isAccessible = true + }.invoke(this) as BaseVariantData + + @Suppress("DEPRECATION") + private val Variant.globalScope: GlobalTaskCreationConfigImpl + get() = component.global as GlobalTaskCreationConfigImpl + + override val Variant.originalApplicationId: String + get() = component.namespace.get() + + override val Variant.hasDynamicFeature: Boolean + get() = component.global.hasDynamicFeatures + + override val Variant.rawAndroidResources: FileCollection + get() { + val allRes: ConfigurableFileCollection = component.services.fileCollection() + + allRes.from( + component.variantDependencies.getArtifactCollection( + AndroidArtifacts.ConsumedConfigType.RUNTIME_CLASSPATH, + AndroidArtifacts.ArtifactScope.ALL, + AndroidArtifacts.ArtifactType.ANDROID_RES + ).artifactFiles + ) + + allRes.from( + component.services.fileCollection(variantData.extraGeneratedResFolders) + .builtBy(listOfNotNull(variantData.extraGeneratedResFolders.builtBy)) + ) + + component.taskContainer.generateApkDataTask?.let { + allRes.from(artifactsImpl.get(InternalArtifactType.MICRO_APK_RES)) + } + + component.sources.res { resSources -> + allRes.from( + resSources.getVariantSources().map { directoryEntries -> + directoryEntries.directoryEntries + .map { + if (it is TaskProviderBasedDirectoryEntryImpl) { + it.directoryProvider + } else { + it.asFiles( + component.services.provider { + component.services.projectInfo.projectDirectory + }) + } + } + } + ) + } + + return allRes + } + override val Variant.sourceSetMap: FileCollection + get() = getFinalArtifactFiles(InternalArtifactType.SOURCE_SET_PATH_MAP) + + override val Variant.localAndroidResources: FileCollection + get() = component.services.fileCollection() + .from(component.sources.res?.getVariantSourcesWithFilter { + !it.isUserAdded && !it.isGenerated + }?.values?.map { + it.map { dirs -> + dirs.map { dir -> + dir.asFileTree + }.reduce { acc, dir -> + acc.plus(dir) + } + } + }) + + override fun Variant.getSingleArtifact(type: Artifact.Single): Provider { + return artifactsImpl.get(type) + } + + override fun Variant.getArtifactCollection( + configType: AndroidArtifacts.ConsumedConfigType, + scope: AndroidArtifacts.ArtifactScope, + artifactType: AndroidArtifacts.ArtifactType + ): ArtifactCollection { + return component.variantDependencies.getArtifactCollection(configType, scope, artifactType) + } + + override fun Variant.getArtifactFileCollection( + configType: AndroidArtifacts.ConsumedConfigType, + scope: AndroidArtifacts.ArtifactScope, + artifactType: AndroidArtifacts.ArtifactType + ): FileCollection { + return component.variantDependencies.getArtifactFileCollection(configType, scope, artifactType) + } + + override val Variant.allArtifacts: Map + get() = TreeMap().also { all -> + SINGLE_ARTIFACT_TYPES.entries.associateTo(all) { (name, type) -> + val artifacts: FileCollection by lazy { + getFinalArtifactFiles(type) + } + name to artifacts + } + MULTIPLE_ARTIFACT_TYPES.entries.associateTo(all) { (name, type) -> + val artifacts: FileCollection by lazy { + getFinalArtifactFiles(type) + } + name to artifacts + } + } + + override val Variant.targetVersion: AndroidVersion + get() = targetSdkVersion + + override val Variant.isApplication: Boolean + get() = component.componentType.isApk + + override val Variant.isLibrary: Boolean + get() = component.componentType.isAar + + override val Variant.isDynamicFeature: Boolean + get() = component.componentType.isDynamicFeature + + override val Variant.aar: FileCollection + get() = getFinalArtifactFiles(SingleArtifact.AAR) + + override val Variant.apk: FileCollection + get() = getFinalArtifactFiles(SingleArtifact.APK) + + override val Variant.mergedManifests: FileCollection + get() = getFinalArtifactFiles(SingleArtifact.MERGED_MANIFEST) + + override val Variant.mergedRes: FileCollection + get() = getFinalArtifactFiles(InternalArtifactType.MERGED_RES) + + override val Variant.mergedNativeLibs: FileCollection + get() = getFinalArtifactFiles(SingleArtifact.MERGED_NATIVE_LIBS) + + override val Variant.mergedAssets: FileCollection + get() = when (this) { + is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.COMPRESSED_ASSETS) + is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.LIBRARY_ASSETS) + else -> TODO("Unsupported variant type: $name@${javaClass.name}") + } + + override val Variant.processedRes: FileCollection + get() = getFinalArtifactFiles(InternalArtifactType.PROCESSED_RES) + + override val Variant.symbolList: FileCollection + get() = when (this) { + is ApplicationVariant -> getFinalArtifactFiles(InternalArtifactType.RUNTIME_SYMBOL_LIST) + is LibraryVariant -> getFinalArtifactFiles(InternalArtifactType.COMPILE_SYMBOL_LIST) + else -> TODO("Unsupported variant type: $name@${javaClass.name}") + } + + override val Variant.symbolListWithPackageName: FileCollection + get() = getFinalArtifactFiles(InternalArtifactType.SYMBOL_LIST_WITH_PACKAGE_NAME) + + override val Variant.dataBindingDependencyArtifacts: FileCollection + get() = getFinalArtifactFiles(InternalArtifactType.DATA_BINDING_DEPENDENCY_ARTIFACTS) + + override val Variant.allClasses: FileCollection + get() = when { + isApplication -> getFinalArtifactFiles(InternalArtifactType.JAVAC) + project.files("build${File.separator}tmp${File.separator}kotlin-classes${File.separator}${name}") + isLibrary -> getFinalArtifactFiles(InternalArtifactType.AAR_MAIN_JAR) + else -> project.files() + } + + override val Variant.buildTools: BuildToolInfo + get() = globalScope.versionedSdkLoader.get().buildToolInfoProvider.get() + + override val Variant.isPrecompileDependenciesResourcesEnabled: Boolean + get() = component.androidResourcesCreationConfig?.isPrecompileDependenciesResourcesEnabled == true + + override fun Variant.getDependencies( + transitive: Boolean, + filter: (ComponentIdentifier) -> Boolean + ): Collection { + val all = getArtifactCollection( + AndroidArtifacts.ConsumedConfigType.RUNTIME_CLASSPATH, + AndroidArtifacts.ArtifactScope.ALL, + AndroidArtifacts.ArtifactType.CLASSES_JAR + ).filter { result -> + filter(result.id.componentIdentifier) + }.associateBy { + it.id.componentIdentifier.displayName + } + val result = if (!transitive) { + runtimeConfiguration.incoming.resolutionResult.root.dependencies.filterIsInstance() + .mapNotNull { + it.selected.id.displayName.takeIf { id -> id in all.keys } + }.associateWith { + all[it]!! + } + } else { + all + } + return result.values.toSet() + } + +} diff --git a/booster-android-gradle-v3_5/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_5/V35Factory.kt b/booster-android-gradle-v8_2/src/main/kotlin/com/didiglobal/booster/android/gradle/v8_2/V82Factory.kt similarity index 53% rename from booster-android-gradle-v3_5/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_5/V35Factory.kt rename to booster-android-gradle-v8_2/src/main/kotlin/com/didiglobal/booster/android/gradle/v8_2/V82Factory.kt index dc6b86a1f..846819410 100644 --- a/booster-android-gradle-v3_5/src/main/kotlin/com/didiglobal/booster/android/gradle/v3_5/V35Factory.kt +++ b/booster-android-gradle-v8_2/src/main/kotlin/com/didiglobal/booster/android/gradle/v8_2/V82Factory.kt @@ -1,4 +1,4 @@ -package com.didiglobal.booster.android.gradle.v3_5 +package com.didiglobal.booster.android.gradle.v8_2 import com.android.repository.Revision import com.didiglobal.booster.gradle.AGPInterface @@ -6,10 +6,10 @@ import com.didiglobal.booster.gradle.AGPInterfaceFactory import com.google.auto.service.AutoService @AutoService(AGPInterfaceFactory::class) -class V35Factory : AGPInterfaceFactory { +class V82Factory : AGPInterfaceFactory { - override val revision: Revision = Revision(3, 5, 0) + override val revision: Revision = Revision(8, 2, 0) - override fun newAGPInterface(): AGPInterface = V35 + override fun newAGPInterface(): AGPInterface = V82 } diff --git a/booster-android-instrument-shared-preferences/build.gradle b/booster-android-instrument-shared-preferences/build.gradle deleted file mode 100644 index 4ad956046..000000000 --- a/booster-android-instrument-shared-preferences/build.gradle +++ /dev/null @@ -1,7 +0,0 @@ -sourceCompatibility = JavaVersion.VERSION_1_8 -targetCompatibility = JavaVersion.VERSION_1_8 - -dependencies { - compileOnly project(':booster-android-api') - implementation project(':booster-android-instrument-thread') -} diff --git a/booster-android-instrument-shared-preferences/src/main/java/com/didiglobal/booster/instrument/ShadowSharedPreferences.java b/booster-android-instrument-shared-preferences/src/main/java/com/didiglobal/booster/instrument/ShadowSharedPreferences.java deleted file mode 100644 index ea264f93b..000000000 --- a/booster-android-instrument-shared-preferences/src/main/java/com/didiglobal/booster/instrument/ShadowSharedPreferences.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.didiglobal.booster.instrument; - -import android.app.Activity; -import android.content.Context; -import android.content.SharedPreferences; -import android.text.TextUtils; -import com.didiglobal.booster.instrument.sharedpreferences.BoosterSharedPreferences; - -public class ShadowSharedPreferences { - - public static SharedPreferences getSharedPreferences(final Context context, String name, final int mode) { - if (TextUtils.isEmpty(name)) { - name = "null"; - } - return BoosterSharedPreferences.getSharedPreferences(context, name); - } - - public static SharedPreferences getDefaultSharedPreferences(Context context) { - return BoosterSharedPreferences.getSharedPreferences(context, getDefaultSharedPreferencesName(context)); - } - - private static String getDefaultSharedPreferencesName(Context context) { - return context.getPackageName() + "_preferences"; - } - - public static SharedPreferences getPreferences(final Activity activity, final int mode) { - return getSharedPreferences(activity.getApplicationContext(), activity.getLocalClassName(), mode); - } - -} diff --git a/booster-android-instrument-shared-preferences/src/main/java/com/didiglobal/booster/instrument/sharedpreferences/BoosterSharedPreferences.java b/booster-android-instrument-shared-preferences/src/main/java/com/didiglobal/booster/instrument/sharedpreferences/BoosterSharedPreferences.java deleted file mode 100755 index 67594addd..000000000 --- a/booster-android-instrument-shared-preferences/src/main/java/com/didiglobal/booster/instrument/sharedpreferences/BoosterSharedPreferences.java +++ /dev/null @@ -1,317 +0,0 @@ -package com.didiglobal.booster.instrument.sharedpreferences; - -import android.app.Application; -import android.content.Context; -import android.content.SharedPreferences; -import android.os.Handler; -import android.os.Looper; -import com.didiglobal.booster.instrument.ShadowExecutors; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.WeakHashMap; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -/** - * @author neighbWang - */ -public final class BoosterSharedPreferences implements SharedPreferences { - private static final ExecutorService SYNC_EXECUTOR = Executors.newCachedThreadPool(); - private static final Map sSharedPreferencesMap = new ConcurrentHashMap<>(); - private static final Object SENTINEL = new Object(); - - private final Map mListeners = Collections.synchronizedMap(new WeakHashMap<>()); - private final Object mLock = new Object(); - private final Object mLoadLock = new Object(); - private final ExecutorService mWriteExecutor; - private final SharedPreferencesManager mManager; - - private volatile boolean mLoaded = false; - private Map mKeyValueMap = new ConcurrentHashMap<>(); - - private BoosterSharedPreferences(final Context context, final String name) { - mWriteExecutor = ShadowExecutors.newOptimizedSingleThreadExecutor(name); - mManager = new SharedPreferencesManager(context, name); - startLoadFromDisk(); - } - - private void startLoadFromDisk() { - synchronized (mLoadLock) { - mLoaded = false; - } - SYNC_EXECUTOR.submit(new LoadThread()); - } - - public static SharedPreferences getSharedPreferences(final Context context, final String name) { - if (context == null) { - throw new IllegalArgumentException("Context can not be null!"); - } - if (!sSharedPreferencesMap.containsKey(name)) { - sSharedPreferencesMap.put(name, new BoosterSharedPreferences(context, name)); - } - return sSharedPreferencesMap.get(name); - } - - @Override - public Map getAll() { - awaitLoadedFromDisk(); - return new HashMap<>(mKeyValueMap); - } - - @Override - public String getString(final String key, final String defaultValue) { - awaitLoadedFromDisk(); - final Object v = mKeyValueMap.get(key); - return v != null ? (String) v : defaultValue; - } - - private void awaitLoadedFromDisk() { - synchronized (mLoadLock) { - while (!mLoaded) { - try { - mLoadLock.wait(); - } catch (InterruptedException ignored) { - } - } - } - } - - @Override - @SuppressWarnings("unchecked") - public Set getStringSet(final String key, final Set defValues) { - awaitLoadedFromDisk(); - final Object v = mKeyValueMap.get(key); - return v != null ? (Set) v : defValues; - } - - @Override - public int getInt(final String key, final int defValue) { - awaitLoadedFromDisk(); - final Object v = mKeyValueMap.get(key); - return v != null ? (Integer) v : defValue; - } - - @Override - public long getLong(final String key, final long defValue) { - awaitLoadedFromDisk(); - final Object v = mKeyValueMap.get(key); - return v != null ? (Long) v : defValue; - } - - @Override - public float getFloat(final String key, final float defValue) { - awaitLoadedFromDisk(); - final Object v = mKeyValueMap.get(key); - return v != null ? (Float) v : defValue; - } - - @Override - public boolean getBoolean(final String key, final boolean defValue) { - awaitLoadedFromDisk(); - final Object v = mKeyValueMap.get(key); - return v != null ? (Boolean) v : defValue; - } - - @Override - public boolean contains(final String key) { - awaitLoadedFromDisk(); - return mKeyValueMap.containsKey(key); - } - - @Override - public Editor edit() { - return new BoosterEditor(); - } - - @Override - public void registerOnSharedPreferenceChangeListener(final OnSharedPreferenceChangeListener onSharedPreferenceChangeListener) { - if (onSharedPreferenceChangeListener != null) { - this.mListeners.put(onSharedPreferenceChangeListener, null); - } - } - - @Override - public void unregisterOnSharedPreferenceChangeListener(final OnSharedPreferenceChangeListener onSharedPreferenceChangeListener) { - if (onSharedPreferenceChangeListener != null) { - this.mListeners.remove(onSharedPreferenceChangeListener); - } - } - - private void loadFromXml() { - synchronized (mLock) { - final Map loadedData = mManager.read(); - this.mKeyValueMap.clear(); - if (loadedData != null) { - for (final Map.Entry entry : loadedData.entrySet()) { - final String key = entry.getKey(); - final Object value = entry.getValue(); - if (key != null && value != null) { - mKeyValueMap.put(key, value); - } - } - } - } - synchronized (mLoadLock) { - mLoaded = true; - mLoadLock.notifyAll(); - } - } - - private class BoosterEditor implements Editor { - - private final Map mModifies = new HashMap<>(); - private volatile boolean mClear = false; - - private BoosterEditor() { - } - - @Override - public Editor putString(final String key, final String value) { - return put(key, value); - } - - @Override - public Editor putStringSet(final String key, final Set values) { - return put(key, new HashSet<>(values)); - } - - @Override - public Editor putInt(final String key, final int value) { - return put(key, value); - } - - @Override - public Editor putLong(final String key, final long value) { - return put(key, value); - } - - @Override - public Editor putFloat(final String key, final float value) { - return put(key, value); - } - - @Override - public Editor putBoolean(final String key, final boolean value) { - return put(key, value); - } - - @Override - public Editor remove(final String key) { - return put(key, SENTINEL); - } - - private synchronized Editor put(final String key, final Object value) { - mModifies.put(key, value); - return this; - } - - @Override - public synchronized Editor clear() { - mClear = true; - return this; - } - - @Override - public boolean commit() { - sync(); - return true; - } - - @Override - public void apply() { - sync(); - } - - private synchronized void sync() { - final Map modifies = new HashMap<>(mModifies); - mModifies.clear(); - awaitLoadedFromDisk(); - final Map mapToWriteToDisk = new HashMap<>(mKeyValueMap); - if (mClear) { - mapToWriteToDisk.clear(); - mClear = false; - } - final boolean hasListeners = mListeners.size() > 0; - final List modifiedKeys = new ArrayList<>(); - for (final Map.Entry e : modifies.entrySet()) { - final String k = e.getKey(); - final Object v = e.getValue(); - if (v == SENTINEL || v == null) { - if (!mapToWriteToDisk.containsKey(k)) { - continue; - } - mapToWriteToDisk.remove(k); - } else { - if (mapToWriteToDisk.containsKey(k)) { - final Object existingValue = mapToWriteToDisk.get(k); - if (existingValue != null && existingValue.equals(v)) { - continue; - } - } - mapToWriteToDisk.put(k, v); - } - if (hasListeners) { - modifiedKeys.add(k); - } - } - mKeyValueMap.clear(); - mKeyValueMap.putAll(mapToWriteToDisk); - mWriteExecutor.execute(new SyncTask(hasListeners, modifiedKeys, mapToWriteToDisk)); - } - - private class SyncTask implements Runnable { - private final boolean mNeedNotifyListener; - private final List mModifiedKeyList; - private final Map mMap; - - SyncTask(boolean needNotifyListener, List modifiedKeys, Map map) { - this.mNeedNotifyListener = needNotifyListener; - this.mModifiedKeyList = modifiedKeys; - this.mMap = map; - } - - @Override - public void run() { - synchronized (mLock) { - if (mManager.write(mMap) && mNeedNotifyListener) { - notifyListeners(mModifiedKeyList); - } - } - } - - private void notifyListeners(final Collection keys) { - if (Looper.myLooper() == Looper.getMainLooper()) { - final OnSharedPreferenceChangeListener[] listeners = mListeners.keySet().toArray(new OnSharedPreferenceChangeListener[0]); - for (final OnSharedPreferenceChangeListener listener : listeners) { - for (String key : keys) { - listener.onSharedPreferenceChanged(BoosterSharedPreferences.this, key); - } - } - } else { - new Handler(Looper.getMainLooper()).post(new Runnable() { - @Override - public void run() { - notifyListeners(keys); - } - }); - } - - } - } - } - - private class LoadThread implements Runnable { - @Override - public void run() { - loadFromXml(); - } - } -} diff --git a/booster-android-instrument-shared-preferences/src/main/java/com/didiglobal/booster/instrument/sharedpreferences/SharedPreferencesManager.java b/booster-android-instrument-shared-preferences/src/main/java/com/didiglobal/booster/instrument/sharedpreferences/SharedPreferencesManager.java deleted file mode 100755 index ab70dfa89..000000000 --- a/booster-android-instrument-shared-preferences/src/main/java/com/didiglobal/booster/instrument/sharedpreferences/SharedPreferencesManager.java +++ /dev/null @@ -1,143 +0,0 @@ -package com.didiglobal.booster.instrument.sharedpreferences; - -import android.content.Context; -import android.util.Log; - -import com.didiglobal.booster.instrument.sharedpreferences.io.XmlUtils; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.Map; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -import static com.didiglobal.booster.instrument.sharedpreferences.io.IoUtils.close; - -/** - * @author neighbWang - */ -class SharedPreferencesManager { - - private static final String TAG = "SharedPreferenceManager"; - private static final int S_IRWXU = 00700; - private static final int S_IRWXG = 00070; - private static final int S_IRWXO = 00007; - - private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); - private final File mSpFile; - private final File mTempFile; - - SharedPreferencesManager(Context context, String name) { - this.mSpFile = new File(getPreferencesDir(context), name + ".xml"); - this.mTempFile = new File(mSpFile.getPath() + ".tmp"); - } - - @SuppressWarnings("ResultOfMethodCallIgnored") - boolean write(final Map map) { - if (!mTempFile.exists()) { - try { - mTempFile.createNewFile(); - } catch (final IOException e) { - prepare(); - try { - mTempFile.createNewFile(); - } catch (IOException ex) { - Log.e(TAG, "Couldn't create tempfile" + mTempFile, ex); - } - return false; - } - } - FileOutputStream fos = null; - try { - fos = new FileOutputStream(mTempFile); - } catch (final FileNotFoundException e) { - Log.e(TAG, "Couldn't write SharedPreferences file " + mTempFile, e); - } - if (fos != null) { - final Lock lock = readWriteLock.writeLock(); - try { - lock.lock(); - XmlUtils.writeMapXml(map, fos); - sync(fos); - if (mSpFile.exists()) { - mSpFile.delete(); - } - return mTempFile.renameTo(mSpFile); - } catch (final Exception e) { - Log.e(TAG, "write message failed : " + e.getMessage()); - return false; - } finally { - lock.unlock(); - close(fos); - } - - } - return false; - } - - Map read() { - if (!mSpFile.exists()) { - return null; - } - prepare(); - if (mSpFile.canRead()) { - BufferedInputStream str = null; - final Lock lock = readWriteLock.readLock(); - try { - lock.lock(); - str = new BufferedInputStream(new FileInputStream(this.mSpFile), 16 * 1024); - return XmlUtils.readMapXml(str); - } catch (Exception e) { - return null; - } finally { - lock.unlock(); - close(str); - } - } - return null; - } - - private void prepare() { - File parent = mSpFile.getParentFile(); - if (!parent.exists()) { - parent.mkdirs(); - } - if (parent.exists() && (!parent.canRead() || !parent.canWrite())) { - setPermissions(parent.getPath()); - } - } - - private static void setPermissions(String path) { - try { - Runtime.getRuntime().exec("chmod " + Integer.toOctalString(S_IRWXU | S_IRWXG | S_IRWXO) + " " + path); - } catch (Exception e) { - Log.w(TAG, e.getMessage()); - } - } - - private static void sync(FileOutputStream stream) { - try { - if (stream != null) { - stream.getFD().sync(); - } - } catch (IOException ignored) { - } - } - - private static File getPreferencesDir(Context context) { - final File files = context.getFilesDir(); - final File data = null != files ? files.getParentFile() : getDataDirFile(context); - return new File(data, "shared_prefs"); - } - - private static File getDataDirFile(Context context) { - final String dataDir = context.getApplicationInfo().dataDir; - return new File(null != dataDir ? dataDir : "/data/data/" + context.getPackageName()); - } - -} diff --git a/booster-android-instrument-shared-preferences/src/main/java/com/didiglobal/booster/instrument/sharedpreferences/io/BoosterXmlSerializer.java b/booster-android-instrument-shared-preferences/src/main/java/com/didiglobal/booster/instrument/sharedpreferences/io/BoosterXmlSerializer.java deleted file mode 100755 index 21e2f2e3b..000000000 --- a/booster-android-instrument-shared-preferences/src/main/java/com/didiglobal/booster/instrument/sharedpreferences/io/BoosterXmlSerializer.java +++ /dev/null @@ -1,335 +0,0 @@ -package com.didiglobal.booster.instrument.sharedpreferences.io; - - -import org.xmlpull.v1.XmlSerializer; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.io.Writer; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.Charset; -import java.nio.charset.CharsetEncoder; -import java.nio.charset.CoderResult; -import java.nio.charset.IllegalCharsetNameException; -import java.nio.charset.UnsupportedCharsetException; - -/** - * @author neighbWang - */ -class BoosterXmlSerializer implements XmlSerializer { - - private static final String[] ESCAPE_TABLE = new String[]{ - null, null, null, null, null, null, null, null, // 0-7 - null, null, null, null, null, null, null, null, // 8-15 - null, null, null, null, null, null, null, null, // 16-23 - null, null, null, null, null, null, null, null, // 24-31 - null, null, """, null, null, null, "&", null, // 32-39 - null, null, null, null, null, null, null, null, // 40-47 - null, null, null, null, null, null, null, null, // 48-55 - null, null, null, null, "<", null, ">", null, // 56-63 - }; - - private static final int BUFFER_LEN = 8192; - private final char[] mText = new char[BUFFER_LEN]; - private int mPos; - private Writer mWriter; - private OutputStream mOutputStream; - private CharsetEncoder mCharset; - private ByteBuffer mBytes = ByteBuffer.allocate(BUFFER_LEN); - private boolean mInTag; - - @Override - public XmlSerializer attribute(final String namespace, final String name, final String value) throws IOException, IllegalArgumentException, IllegalStateException { - append(' '); - if (namespace != null) { - append(namespace); - append(':'); - } - append(name); - append("=\""); - escapeAndAppendString(value); - append('"'); - return this; - } - - @Override - public void cdsect(final String text) throws IllegalArgumentException, IllegalStateException { - throw new UnsupportedOperationException(); - } - - @Override - public void comment(final String text) throws IllegalArgumentException, IllegalStateException { - throw new UnsupportedOperationException(); - } - - @Override - public void docdecl(final String text) throws IllegalArgumentException, IllegalStateException { - throw new UnsupportedOperationException(); - } - - @Override - public void endDocument() throws IOException, IllegalArgumentException, IllegalStateException { - flush(); - } - - @Override - public XmlSerializer endTag(final String namespace, final String name) throws IOException, IllegalArgumentException, IllegalStateException { - if (mInTag) { - append(" />\n"); - } else { - append("\n"); - } - mInTag = false; - return this; - } - - @Override - public void entityRef(final String text) throws IllegalArgumentException, IllegalStateException { - throw new UnsupportedOperationException(); - } - - private void flushBytes() throws IOException { - int position; - if ((position = mBytes.position()) > 0) { - mBytes.flip(); - mOutputStream.write(mBytes.array(), 0, position); - mBytes.clear(); - } - } - - @Override - public void flush() throws IOException { - if (mPos > 0) { - if (mOutputStream != null) { - final CharBuffer charBuffer = CharBuffer.wrap(mText, 0, mPos); - CoderResult result = mCharset.encode(charBuffer, mBytes, true); - while (true) { - if (result.isError()) { - throw new IOException(result.toString()); - } else if (result.isOverflow()) { - flushBytes(); - result = mCharset.encode(charBuffer, mBytes, true); - continue; - } - break; - } - flushBytes(); - mOutputStream.flush(); - } else { - mWriter.write(mText, 0, mPos); - mWriter.flush(); - } - mPos = 0; - } - } - - @Override - public int getDepth() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean getFeature(String name) { - throw new UnsupportedOperationException(); - } - - @Override - public String getName() { - throw new UnsupportedOperationException(); - } - - @Override - public String getNamespace() { - throw new UnsupportedOperationException(); - } - - @Override - public String getPrefix(final String namespace, boolean generatePrefix) throws IllegalArgumentException { - throw new UnsupportedOperationException(); - } - - @Override - public Object getProperty(final String name) { - throw new UnsupportedOperationException(); - } - - @Override - public void ignorableWhitespace(final String text) throws IllegalArgumentException, IllegalStateException { - throw new UnsupportedOperationException(); - } - - @Override - public void processingInstruction(final String text) throws IllegalArgumentException, IllegalStateException { - throw new UnsupportedOperationException(); - } - - @Override - public void setFeature(final String name, final boolean state) throws IllegalArgumentException, IllegalStateException { - if (name.equals("http://xmlpull.org/v1/doc/features.html#indent-output")) { - return; - } - throw new UnsupportedOperationException(); - } - - @Override - public void setOutput(final OutputStream os, final String encoding) throws IOException, IllegalArgumentException, IllegalStateException { - if (os == null) - throw new IllegalArgumentException(); - try { - mCharset = Charset.forName(encoding).newEncoder(); - } catch (IllegalCharsetNameException | UnsupportedCharsetException e) { - throw (UnsupportedEncodingException) (new UnsupportedEncodingException(encoding).initCause(e)); - } - mOutputStream = os; - } - - @Override - public void setOutput(final Writer writer) throws IllegalArgumentException, IllegalStateException { - mWriter = writer; - } - - @Override - public void setPrefix(final String prefix, final String namespace) throws IllegalArgumentException, IllegalStateException { - throw new UnsupportedOperationException(); - } - - @Override - public void setProperty(final String name, final Object value) throws IllegalArgumentException, IllegalStateException { - throw new UnsupportedOperationException(); - } - - @Override - public void startDocument(final String encoding, final Boolean standalone) throws IOException, IllegalArgumentException, IllegalStateException { - append("\n"); - } - - @Override - public XmlSerializer startTag(final String namespace, final String name) throws IOException, IllegalArgumentException, IllegalStateException { - if (mInTag) { - append(">\n"); - } - append('<'); - if (namespace != null) { - append(namespace); - append(':'); - } - append(name); - mInTag = true; - return this; - } - - @Override - public XmlSerializer text(final char[] buf, final int start, final int len) throws IOException, IllegalArgumentException, IllegalStateException { - if (mInTag) { - append(">"); - mInTag = false; - } - escapeAndAppendString(buf, start, len); - return this; - } - - @Override - public XmlSerializer text(final String text) throws IOException, IllegalArgumentException, IllegalStateException { - if (mInTag) { - append(">"); - mInTag = false; - } - escapeAndAppendString(text); - return this; - } - - private void append(final char c) throws IOException { - int pos = mPos; - if (pos >= (BUFFER_LEN - 1)) { - flush(); - pos = mPos; - } - mText[pos] = c; - mPos = pos + 1; - } - - private void append(final String str, int i, final int length) throws IOException { - if (length > BUFFER_LEN) { - final int end = i + length; - while (i < end) { - int next = i + BUFFER_LEN; - append(str, i, next < end ? BUFFER_LEN : (end - i)); - i = next; - } - return; - } - int pos = mPos; - if ((pos + length) > BUFFER_LEN) { - flush(); - pos = mPos; - } - str.getChars(i, i + length, mText, pos); - mPos = pos + length; - } - - private void append(final char[] buf, int i, final int length) throws IOException { - if (length > BUFFER_LEN) { - final int end = i + length; - while (i < end) { - int next = i + BUFFER_LEN; - append(buf, i, next < end ? BUFFER_LEN : (end - i)); - i = next; - } - return; - } - int pos = mPos; - if ((pos + length) > BUFFER_LEN) { - flush(); - pos = mPos; - } - System.arraycopy(buf, i, mText, pos, length); - mPos = pos + length; - } - - private void append(final String str) throws IOException { - append(str, 0, str.length()); - } - - private void escapeAndAppendString(final String string) throws IOException { - final int N = string.length(); - final char NE = (char) ESCAPE_TABLE.length; - int lastPos = 0; - int pos; - for (pos = 0; pos < N; pos++) { - char c = string.charAt(pos); - if (c >= NE) continue; - final String escape = ESCAPE_TABLE[c]; - if (escape == null) continue; - if (lastPos < pos) append(string, lastPos, pos - lastPos); - lastPos = pos + 1; - append(escape); - } - if (lastPos < pos) append(string, lastPos, pos - lastPos); - } - - private void escapeAndAppendString(final char[] buf, final int start, final int len) throws IOException { - final char NE = (char) ESCAPE_TABLE.length; - int end = start + len; - int lastPos = start; - int pos; - for (pos = start; pos < end; pos++) { - char c = buf[pos]; - if (c >= NE) continue; - String escape = ESCAPE_TABLE[c]; - if (escape == null) continue; - if (lastPos < pos) append(buf, lastPos, pos - lastPos); - lastPos = pos + 1; - append(escape); - } - if (lastPos < pos) append(buf, lastPos, pos - lastPos); - } - -} \ No newline at end of file diff --git a/booster-android-instrument-shared-preferences/src/main/java/com/didiglobal/booster/instrument/sharedpreferences/io/IoUtils.java b/booster-android-instrument-shared-preferences/src/main/java/com/didiglobal/booster/instrument/sharedpreferences/io/IoUtils.java deleted file mode 100644 index 3566336c2..000000000 --- a/booster-android-instrument-shared-preferences/src/main/java/com/didiglobal/booster/instrument/sharedpreferences/io/IoUtils.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.didiglobal.booster.instrument.sharedpreferences.io; - -import java.io.Closeable; -import java.io.IOException; - -/** - * @author neighbWang - */ -public final class IoUtils { - - private IoUtils() { - } - - public static void close(Closeable closeable) { - if (closeable != null) { - try { - closeable.close(); - } catch (IOException ignored) { - } - } - } -} diff --git a/booster-android-instrument-shared-preferences/src/main/java/com/didiglobal/booster/instrument/sharedpreferences/io/XmlUtils.java b/booster-android-instrument-shared-preferences/src/main/java/com/didiglobal/booster/instrument/sharedpreferences/io/XmlUtils.java deleted file mode 100755 index 79a10a357..000000000 --- a/booster-android-instrument-shared-preferences/src/main/java/com/didiglobal/booster/instrument/sharedpreferences/io/XmlUtils.java +++ /dev/null @@ -1,389 +0,0 @@ -package com.didiglobal.booster.instrument.sharedpreferences.io; - -import android.util.Xml; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * @author neighbWang - */ -public final class XmlUtils { - - public static void writeMapXml(final Map val, final OutputStream out) throws XmlPullParserException, java.io.IOException { - final XmlSerializer serializer = new BoosterXmlSerializer(); - serializer.setOutput(out, "utf-8"); - serializer.startDocument(null, true); - serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); - writeMapXml(val, null, serializer); - serializer.endDocument(); - } - - private static void writeMapXml(final Map val, final String name, final XmlSerializer out) throws XmlPullParserException, java.io.IOException { - if (val == null) { - out.startTag(null, "null"); - out.endTag(null, "null"); - return; - } - final Set s = val.entrySet(); - final Iterator i = s.iterator(); - out.startTag(null, "map"); - if (name != null) { - out.attribute(null, "name", name); - } - while (i.hasNext()) { - final Map.Entry e = (Map.Entry) i.next(); - writeValueXml(e.getValue(), (String) e.getKey(), out); - } - out.endTag(null, "map"); - } - - private static void writeListXml(final List val, final String name, final XmlSerializer out) throws XmlPullParserException, java.io.IOException { - if (val == null) { - out.startTag(null, "null"); - out.endTag(null, "null"); - return; - } - out.startTag(null, "list"); - if (name != null) { - out.attribute(null, "name", name); - } - final int N = val.size(); - int i = 0; - while (i < N) { - writeValueXml(val.get(i), null, out); - i++; - } - out.endTag(null, "list"); - } - - private static void writeSetXml(Set val, String name, XmlSerializer out) throws XmlPullParserException, java.io.IOException { - if (val == null) { - out.startTag(null, "null"); - out.endTag(null, "null"); - return; - } - out.startTag(null, "set"); - if (name != null) { - out.attribute(null, "name", name); - } - for (Object v : val) { - writeValueXml(v, null, out); - } - out.endTag(null, "set"); - } - - private static void writeByteArrayXml(final byte[] val, final String name, final XmlSerializer out) throws java.io.IOException { - if (val == null) { - out.startTag(null, "null"); - out.endTag(null, "null"); - return; - } - out.startTag(null, "byte-array"); - if (name != null) { - out.attribute(null, "name", name); - } - out.attribute(null, "num", Integer.toString(val.length)); - final StringBuilder sb = new StringBuilder(val.length * 2); - for (int b : val) { - int h = b >> 4; - sb.append(h >= 10 ? ('a' + h - 10) : ('0' + h)); - h = b & 0xff; - sb.append(h >= 10 ? ('a' + h - 10) : ('0' + h)); - } - out.text(sb.toString()); - out.endTag(null, "byte-array"); - } - - private static void writeIntArrayXml(final int[] val, final String name, final XmlSerializer out) throws java.io.IOException { - if (val == null) { - out.startTag(null, "null"); - out.endTag(null, "null"); - return; - } - out.startTag(null, "int-array"); - if (name != null) { - out.attribute(null, "name", name); - } - out.attribute(null, "num", Integer.toString(val.length)); - for (int value : val) { - out.startTag(null, "item"); - out.attribute(null, "value", Integer.toString(value)); - out.endTag(null, "item"); - } - out.endTag(null, "int-array"); - } - - private static void writeValueXml(final Object v, final String name, final XmlSerializer out) throws XmlPullParserException, java.io.IOException { - String typeStr; - if (v == null) { - out.startTag(null, "null"); - if (name != null) { - out.attribute(null, "name", name); - } - out.endTag(null, "null"); - return; - } else if (v instanceof String) { - out.startTag(null, "string"); - if (name != null) { - out.attribute(null, "name", name); - } - out.text(v.toString()); - out.endTag(null, "string"); - return; - } else if (v instanceof Integer) { - typeStr = "int"; - } else if (v instanceof Long) { - typeStr = "long"; - } else if (v instanceof Float) { - typeStr = "float"; - } else if (v instanceof Double) { - typeStr = "double"; - } else if (v instanceof Boolean) { - typeStr = "boolean"; - } else if (v instanceof byte[]) { - writeByteArrayXml((byte[]) v, name, out); - return; - } else if (v instanceof int[]) { - writeIntArrayXml((int[]) v, name, out); - return; - } else if (v instanceof Map) { - writeMapXml((Map) v, name, out); - return; - } else if (v instanceof List) { - writeListXml((List) v, name, out); - return; - } else if (v instanceof Set) { - writeSetXml((Set) v, name, out); - return; - } else if (v instanceof CharSequence) { - out.startTag(null, "string"); - if (name != null) { - out.attribute(null, "name", name); - } - out.text(v.toString()); - out.endTag(null, "string"); - return; - } else { - throw new RuntimeException("writeValueXml: unable to write value " + v); - } - out.startTag(null, typeStr); - if (name != null) { - out.attribute(null, "name", name); - } - out.attribute(null, "value", v.toString()); - out.endTag(null, typeStr); - } - - @SuppressWarnings("unchecked") - public static HashMap readMapXml(final InputStream in) throws XmlPullParserException, java.io.IOException { - final XmlPullParser parser = Xml.newPullParser(); - parser.setInput(in, null); - return (HashMap) readValueXml(parser, new String[1]); - } - - private static Map readThisMapXml(XmlPullParser parser, String[] name) throws XmlPullParserException, java.io.IOException { - final Map map = new HashMap<>(); - int eventType = parser.getEventType(); - do { - if (eventType == parser.START_TAG) { - Object val = readThisValueXml(parser, name); - if (name[0] != null) { - map.put(name[0], val); - } else { - throw new XmlPullParserException("Map value without name attribute: " + parser.getName()); - } - } else if (eventType == parser.END_TAG) { - if ("map".equals(parser.getName())) { - return map; - } - throw new XmlPullParserException("Expected map end tag at: " + parser.getName()); - } - eventType = parser.next(); - } while (eventType != parser.END_DOCUMENT); - throw new XmlPullParserException("Document ended before map end tag"); - } - - private static List readThisListXml(final XmlPullParser parser, final String[] name) - throws XmlPullParserException, java.io.IOException { - final List list = new ArrayList<>(); - int eventType = parser.getEventType(); - do { - if (eventType == parser.START_TAG) { - Object val = readThisValueXml(parser, name); - list.add(val); - } else if (eventType == parser.END_TAG) { - if (parser.getName().equals("list")) { - return list; - } - throw new XmlPullParserException("Expected list end tag at: " + parser.getName()); - } - eventType = parser.next(); - } while (eventType != parser.END_DOCUMENT); - throw new XmlPullParserException("Document ended before list end tag"); - } - - private static Set readThisSetXml(XmlPullParser parser, String[] name) throws XmlPullParserException, java.io.IOException { - final Set set = new HashSet<>(); - int eventType = parser.getEventType(); - do { - if (eventType == parser.START_TAG) { - Object val = readThisValueXml(parser, name); - set.add(val); - } else if (eventType == parser.END_TAG) { - if (parser.getName().equals("set")) { - return set; - } - throw new XmlPullParserException("Expected set end tag at: " + parser.getName()); - } - eventType = parser.next(); - } while (eventType != parser.END_DOCUMENT); - - throw new XmlPullParserException("Document ended before set end tag"); - } - - private static int[] readThisIntArrayXml(final XmlPullParser parser) throws XmlPullParserException, java.io.IOException { - int num; - try { - num = Integer.parseInt(parser.getAttributeValue(null, "num")); - } catch (NullPointerException e) { - throw new XmlPullParserException("Need num attribute in byte-array"); - } catch (NumberFormatException e) { - throw new XmlPullParserException("Not a number in num attribute in byte-array"); - } - final int[] array = new int[num]; - int i = 0; - int eventType = parser.getEventType(); - do { - if (eventType == parser.START_TAG) { - if (parser.getName().equals("item")) { - try { - array[i] = Integer.parseInt(parser.getAttributeValue(null, "value")); - } catch (NullPointerException e) { - throw new XmlPullParserException("Need value attribute in item"); - } catch (NumberFormatException e) { - throw new XmlPullParserException("Not a number in value attribute in item"); - } - } else { - throw new XmlPullParserException("Expected item tag at: " + parser.getName()); - } - } else if (eventType == parser.END_TAG) { - if ("int-array".equals(parser.getName())) { - return array; - } else if (parser.getName().equals("item")) { - i++; - } else { - throw new XmlPullParserException("Expected `int-array` end tag at: " + parser.getName()); - } - } - eventType = parser.next(); - } while (eventType != parser.END_DOCUMENT); - throw new XmlPullParserException("Document ended before `int-array` end tag"); - } - - private static Object readValueXml(XmlPullParser parser, String[] name) - throws XmlPullParserException, java.io.IOException { - int eventType = parser.getEventType(); - do { - if (eventType == parser.START_TAG) { - return readThisValueXml(parser, name); - } else if (eventType == parser.END_TAG) { - throw new XmlPullParserException("Unexpected end tag at: " + parser.getName()); - } else if (eventType == parser.TEXT) { - throw new XmlPullParserException("Unexpected text: " + parser.getText()); - } - eventType = parser.next(); - } while (eventType != parser.END_DOCUMENT); - throw new XmlPullParserException("Unexpected end of document"); - } - - private static Object readThisValueXml(final XmlPullParser parser, final String[] name) throws XmlPullParserException, java.io.IOException { - final String valueName = parser.getAttributeValue(null, "name"); - final String tagName = parser.getName(); - Object res; - switch (tagName) { - case "null": - res = null; - break; - case "string": - final StringBuilder value = new StringBuilder(); - int eventType; - while ((eventType = parser.next()) != parser.END_DOCUMENT) { - if (eventType == parser.END_TAG) { - if (parser.getName().equals("string")) { - name[0] = valueName; - return value.toString(); - } - throw new XmlPullParserException("Unexpected end tag in : " + parser.getName()); - } else if (eventType == parser.TEXT) { - value.append(parser.getText()); - } else if (eventType == parser.START_TAG) { - throw new XmlPullParserException("Unexpected start tag in : " + parser.getName()); - } - } - throw new XmlPullParserException("Unexpected end of document in "); - case "int": - res = Integer.parseInt(parser.getAttributeValue(null, "value")); - break; - case "long": - res = Long.valueOf(parser.getAttributeValue(null, "value")); - break; - case "float": - res = new Float(parser.getAttributeValue(null, "value")); - break; - case "double": - res = new Double(parser.getAttributeValue(null, "value")); - break; - case "boolean": - res = Boolean.valueOf(parser.getAttributeValue(null, "value")); - break; - case "int-array": - parser.next(); - res = readThisIntArrayXml(parser); - name[0] = valueName; - return res; - case "map": - parser.next(); - res = readThisMapXml(parser, name); - name[0] = valueName; - return res; - case "list": - parser.next(); - res = readThisListXml(parser, name); - name[0] = valueName; - return res; - case "set": - parser.next(); - res = readThisSetXml(parser, name); - name[0] = valueName; - return res; - default: - throw new XmlPullParserException("Unknown tag: " + tagName); - } - int eventType; - while ((eventType = parser.next()) != parser.END_DOCUMENT) { - if (eventType == parser.END_TAG) { - if (parser.getName().equals(tagName)) { - name[0] = valueName; - return res; - } - throw new XmlPullParserException("Unexpected end tag in <" + tagName + ">: " + parser.getName()); - } else if (eventType == parser.TEXT) { - throw new XmlPullParserException("Unexpected text in <" + tagName + ">: " + parser.getName()); - } else if (eventType == parser.START_TAG) { - throw new XmlPullParserException("Unexpected start tag in <" + tagName + ">: " + parser.getName()); - } - } - throw new XmlPullParserException("Unexpected end of document in <" + tagName + ">"); - } -} \ No newline at end of file diff --git a/booster-android-instrument-webview/build.gradle b/booster-android-instrument-webview/build.gradle deleted file mode 100644 index 30c2ad740..000000000 --- a/booster-android-instrument-webview/build.gradle +++ /dev/null @@ -1,7 +0,0 @@ -sourceCompatibility = JavaVersion.VERSION_1_8 -targetCompatibility = JavaVersion.VERSION_1_8 - -dependencies { - compileOnly project(':booster-android-api') - implementation project(':booster-android-instrument') -} \ No newline at end of file diff --git a/booster-android-instrument-webview/src/main/java/com/didiglobal/booster/instrument/ShadowWebView.java b/booster-android-instrument-webview/src/main/java/com/didiglobal/booster/instrument/ShadowWebView.java deleted file mode 100644 index 29bbd4fa7..000000000 --- a/booster-android-instrument-webview/src/main/java/com/didiglobal/booster/instrument/ShadowWebView.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.didiglobal.booster.instrument; - -import android.app.Application; -import android.content.Context; -import android.os.Build; -import android.os.Handler; -import android.os.Looper; -import android.os.MessageQueue; -import android.os.SystemClock; -import android.util.Log; -import android.webkit.WebView; - -import static com.didiglobal.booster.instrument.Constants.TAG; -import static com.didiglobal.booster.instrument.Reflection.invokeMethod; -import static com.didiglobal.booster.instrument.Reflection.invokeStaticMethod; - -/** - * @author neighbWang - */ -public class ShadowWebView { - - public static void preloadWebView(final Application app) { - new Handler(Looper.getMainLooper()).post(new Runnable() { - @Override - public void run() { - try { - Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() { - @Override - public boolean queueIdle() { - startChromiumEngine(app); - return false; - } - }); - } catch (final Throwable t) { - Log.e(TAG, "Oops!", t); - } - } - }); - } - - private static void startChromiumEngine(final Context context) { - try { - final long t0 = SystemClock.uptimeMillis(); - final Object provider = invokeStaticMethod(Class.forName("android.webkit.WebViewFactory"), "getProvider"); - invokeMethod(provider, "startYourEngines", new Class[]{boolean.class}, new Object[]{true}); - Log.i(TAG, "Start chromium engine complete: " + (SystemClock.uptimeMillis() - t0) + " ms"); - if (Build.VERSION.SDK_INT >= 28) { - String processName = Application.getProcessName(); - String packageName = context.getPackageName(); - if (!packageName.equals(processName)) { - WebView.setDataDirectorySuffix(processName); - } - } - } catch (final Throwable t) { - Log.e(TAG, "Start chromium engine error", t); - } - } -} \ No newline at end of file diff --git a/booster-api/build.gradle b/booster-api/build.gradle index cc1d3db16..fb5b7f264 100644 --- a/booster-api/build.gradle +++ b/booster-api/build.gradle @@ -7,6 +7,6 @@ dependencies { api project(':booster-transform-util') api gradleApi() api 'com.google.auto.service:auto-service:1.0' - compileOnly 'com.android.tools.build:gradle:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' + compileOnly 'com.android.tools.build:gradle:8.0.0' + testCompileOnly 'com.android.tools.build:gradle:8.0.0' } diff --git a/booster-api/src/main/kotlin/com/didiglobal/booster/RelativeResourceUtils.kt b/booster-api/src/main/kotlin/com/didiglobal/booster/RelativeResourceUtils.kt new file mode 100644 index 000000000..b16aae0f3 --- /dev/null +++ b/booster-api/src/main/kotlin/com/didiglobal/booster/RelativeResourceUtils.kt @@ -0,0 +1,155 @@ +@file:JvmName("RelativeResourceUtils") + +package com.didiglobal.booster + +import java.io.File +import java.io.IOException +import java.nio.file.FileSystem +import java.nio.file.FileSystems +import kotlin.IllegalStateException + +private const val separator: String = ":/" + +/** + * Determines a resource file path relative to the source set containing the resource. + * + * The absolute path to the module source set is identified by the source set ordering of a module. + * Format of the returned String is `:`. + */ +fun getRelativeSourceSetPath(resourceFile: File, moduleSourceSets: Map) + : String { + val absoluteResFilePath = resourceFile.absolutePath + for ((identifier, absoluteSourceSetPath) in moduleSourceSets.entries) { + if (absoluteResFilePath.startsWith(absoluteSourceSetPath)) { + val invariantFilePath = resourceFile.absoluteFile.invariantSeparatorsPath + val resIndex = File(absoluteSourceSetPath).absoluteFile.invariantSeparatorsPath.length + val relativePathToSourceSet = invariantFilePath.substring(resIndex + 1) + return "$identifier$separator$relativePathToSourceSet" + } + } + + throw IllegalArgumentException( + "Unable to locate resourceFile ($absoluteResFilePath) in source-sets.") +} + +/** + * Converts a source set identified relative resource path to an absolute path. + * + * The source set identifier before the separator is replaced with the absolute source set + * path and then concatenated with the path after the separator. + */ +fun relativeResourcePathToAbsolutePath( + relativePath: String, + sourceSetPathMap: Map, + fileSystem: FileSystem = FileSystems.getDefault()): String { + return relativeResourcePathToAbsolutePath(sourceSetPathMap, fileSystem)(relativePath) +} + +fun relativeResourcePathToAbsolutePath( + sourceSetPathMap: Map, + fileSystem: FileSystem = FileSystems.getDefault() +): (String) -> String { + return { relativePath: String -> + if (sourceSetPathMap.none()) { + throw IllegalStateException( + """Unable to get absolute path from $relativePath + because no relative root paths are present.""" + ) + } + val separatorIndex = relativePath.indexOf(separator) + if (separatorIndex == -1) { + throw IllegalArgumentException( + """Source set identifier and relative path must be separated by a "$separator". + Relative path: $relativePath""" + ) + } + val sourceSetPrefix = relativePath.substring(0, separatorIndex) + val resourcePathFromSourceSet = + relativePath.substring(separatorIndex + separator.lastIndex, relativePath.length) + val systemRelativePath = if ("/" != fileSystem.separator) { + resourcePathFromSourceSet.replace("/", fileSystem.separator) + } else { + resourcePathFromSourceSet + } + val absolutePath = sourceSetPathMap[sourceSetPrefix] + ?: throw NoSuchElementException( + """Unable to get absolute path from $relativePath + because $sourceSetPrefix is not key in sourceSetPathMap.""" + ) + "$absolutePath$systemRelativePath" + } +} + +/** + * Parses identifier and file path into a map from a file + * in the format 'packageName.projectName-sortedOrderPosition absolutePath'. + */ +fun readFromSourceSetPathsFile(artifactFile: File): Map { + if (!artifactFile.exists() || !artifactFile.isFile) { + throw IOException("$artifactFile does not exist or is not a file.") + } + return artifactFile.bufferedReader().use { bufferedReader -> + bufferedReader.lineSequence().associate { + it.substringBefore(" ") to it.substringAfter(" ") + } + } +} + +/** + * Writes a file containing a mapping of resource source-set absolute paths to a unique identifier + * in the format of 'packageName.projectName-sortedOrderPosition absolutePath'. + */ +fun writeIdentifiedSourceSetsFile( + resourceSourceSets: List, + namespace: String, + projectPath: String, + output: File +) { + output.bufferedWriter().use { bw -> + getIdentifiedSourceSetMap(resourceSourceSets, namespace, projectPath).forEach { + bw.write("${it.key} ${it.value}\n") + } + } +} + +/** + * Using a list of files following the format produced by writeIdentifiedSourceSetsFile, + * contents of each file are added to a single table which maps the source set identifier + * to the absolute path of the source set. + */ +fun mergeIdentifiedSourceSetFiles(sourceSetFiles: Collection) : Map { + return mutableMapOf() + .also { identifiedSourceMap -> + sourceSetFiles + .map { readFromSourceSetPathsFile(it) } + .forEach { identifiedSourceMap.putAll(it) } + } +} + +fun getIdentifiedSourceSetMap( + resourceSourceSets: List, + namespace: String, + projectPath: String) : Map { + val projectName = projectPath.substringAfterLast(":") + var i = 0 + return resourceSourceSets + .asSequence() + .filterNotNull() + .distinctBy(File::invariantSeparatorsPath) + .sortedBy(File::invariantSeparatorsPath) + .associate { sourceSet -> + val sourceSetFolderName = sourceSet.parentFile.name + val appendProjectName = + if (namespace.endsWith(projectName)) "" else ".$projectName" + val appId = "$namespace$appendProjectName-$sourceSetFolderName-${i++}" + appId to sourceSet.absolutePath + } +} + +/** + * Verifies if a string is relative resource sourceset filepath. This is for cases where it is + * not possible to determine if relative resource filepaths are enabled by default. + */ +fun isRelativeSourceSetResource(filepath: String) : Boolean { + return filepath.contains(separator) +} diff --git a/booster-api/src/main/kotlin/com/didiglobal/booster/transform/VariantTransformHelper.kt b/booster-api/src/main/kotlin/com/didiglobal/booster/transform/VariantTransformHelper.kt index e20e4084b..c8cc553c2 100644 --- a/booster-api/src/main/kotlin/com/didiglobal/booster/transform/VariantTransformHelper.kt +++ b/booster-api/src/main/kotlin/com/didiglobal/booster/transform/VariantTransformHelper.kt @@ -1,31 +1,12 @@ package com.didiglobal.booster.transform import com.android.SdkConstants -import com.android.build.gradle.api.BaseVariant -import com.didiglobal.booster.gradle.aar -import com.didiglobal.booster.gradle.allArtifacts -import com.didiglobal.booster.gradle.allClasses -import com.didiglobal.booster.gradle.apk -import com.didiglobal.booster.gradle.mergedAssets -import com.didiglobal.booster.gradle.mergedManifests -import com.didiglobal.booster.gradle.mergedRes -import com.didiglobal.booster.gradle.platform -import com.didiglobal.booster.gradle.processedRes -import com.didiglobal.booster.gradle.project -import com.didiglobal.booster.gradle.symbolList -import com.didiglobal.booster.gradle.symbolListWithPackageName +import com.android.build.api.variant.Variant +import com.didiglobal.booster.gradle.* import com.didiglobal.booster.kotlinx.search -import com.didiglobal.booster.transform.util.TransformHelper import java.io.File -/** - * Represents transform helper associates with variant - * - * @author johnsonlee - */ -class VariantTransformHelper(variant: BaseVariant, input: File) : TransformHelper(input, variant.platform, variant.artifacts, variant.applicationId, variant.name) - -val BaseVariant.artifacts: ArtifactManager +val Variant.artifactManager: ArtifactManager get() = object : ArtifactManager { override fun get(type: String): Collection = when (type) { diff --git a/booster-gradle-plugin/build.gradle b/booster-gradle-plugin/build.gradle index 7ac985ecc..815794b2c 100644 --- a/booster-gradle-plugin/build.gradle +++ b/booster-gradle-plugin/build.gradle @@ -5,9 +5,8 @@ dependencies { api gradleApi() api project(':booster-annotations') api project(':booster-api') - api project(':booster-transform-util') - compileOnly 'com.android.tools.build:gradle:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' + compileOnly 'com.android.tools.build:gradle:8.0.0' + testCompileOnly 'com.android.tools.build:gradle:8.0.0' } apply plugin: 'java-gradle-plugin' diff --git a/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/BoosterPlugin.kt b/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/BoosterPlugin.kt index d42b1c286..583073a77 100644 --- a/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/BoosterPlugin.kt +++ b/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/BoosterPlugin.kt @@ -1,9 +1,13 @@ package com.didiglobal.booster.gradle +import com.android.build.api.artifact.ScopedArtifact +import com.android.build.api.variant.AndroidComponentsExtension +import com.android.build.api.variant.ScopedArtifacts import com.android.build.gradle.AppExtension import com.android.build.gradle.BaseExtension import com.android.build.gradle.LibraryExtension import com.android.build.gradle.api.BaseVariant +import com.didiglobal.booster.kotlinx.capitalized import com.didiglobal.booster.task.spi.VariantProcessor import org.gradle.api.GradleException import org.gradle.api.Plugin @@ -18,23 +22,38 @@ class BoosterPlugin : Plugin { override fun apply(project: Project) { project.extensions.findByName("android") ?: throw GradleException("$project is not an Android project") + registerTransform(project) + setupTasks(project) + } - if (!GTE_V3_6) { - project.gradle.addListener(BoosterTransformTaskExecutionListener(project)) - } - + private fun setupTasks(project: Project) { val processors = loadVariantProcessors(project) + project.setup(processors) + if (project.state.executed) { - project.setup(processors) + project.legacySetup(processors) } else { project.afterEvaluate { - project.setup(processors) + project.legacySetup(processors) } } - project.getAndroid().registerTransform(BoosterTransform.newInstance(project)) } private fun Project.setup(processors: List) { + val androidComponents = project.extensions.getByType(AndroidComponentsExtension::class.java) + androidComponents.beforeVariants { variantBuilder -> + processors.forEach { processor -> + processor.beforeProcess(variantBuilder) + } + } + androidComponents.onVariants { variant -> + processors.forEach { processor -> + processor.process(variant) + } + } + } + + private fun Project.legacySetup(processors: List) { val android = project.getAndroid() when (android) { is AppExtension -> android.applicationVariants @@ -49,5 +68,26 @@ class BoosterPlugin : Plugin { } } + private fun registerTransform(project: Project) { + val androidComponents = project.extensions.getByType(AndroidComponentsExtension::class.java) + androidComponents.onVariants { variant -> + val transform = project.tasks.register( + "transform${variant.name.capitalized()}ClassesWithBooster", + BoosterTransformTask::class.java + ) { + it.transformers = loadTransformers(project.buildscript.classLoader) + it.variant = variant + it.applicationId = variant.namespace.get() + it.bootClasspath = androidComponents.sdkComponents.bootClasspath + } + variant.artifacts.forScope(ScopedArtifacts.Scope.ALL) + .use(transform).toTransform( + ScopedArtifact.CLASSES, + BoosterTransformTask::allJars, + BoosterTransformTask::allDirectories, + BoosterTransformTask::output + ) + } + } } diff --git a/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/BoosterTransform.kt b/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/BoosterTransform.kt deleted file mode 100644 index 172e61962..000000000 --- a/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/BoosterTransform.kt +++ /dev/null @@ -1,77 +0,0 @@ -package com.didiglobal.booster.gradle - -import com.android.build.api.transform.QualifiedContent -import com.android.build.api.transform.Transform -import com.android.build.api.transform.TransformInvocation -import com.android.build.gradle.internal.pipeline.TransformManager -import com.didiglobal.booster.gradle.internal.BoosterTransformV34 -import org.gradle.api.Project - -/** - * Represents the transform base - * - * @author johnsonlee - */ -open class BoosterTransform protected constructor( - internal val parameter: TransformParameter -) : Transform() { - - internal val verifyEnabled by lazy { - parameter.properties[OPT_TRANSFORM_VERIFY]?.toString()?.toBoolean() ?: false - } - - override fun getName() = parameter.name - - override fun isIncremental() = !verifyEnabled - - override fun isCacheable() = !verifyEnabled - - override fun getInputTypes(): MutableSet = TransformManager.CONTENT_CLASS - - override fun getScopes(): MutableSet = when { - parameter.transformers.isEmpty() -> mutableSetOf() - parameter.plugins.hasPlugin("com.android.library") -> SCOPE_PROJECT - parameter.plugins.hasPlugin("com.android.application") -> SCOPE_FULL_PROJECT - parameter.plugins.hasPlugin("com.android.dynamic-feature") -> SCOPE_FULL_WITH_FEATURES - else -> TODO("Not an Android project") - } - - override fun getReferencedScopes(): MutableSet = when { - parameter.transformers.isEmpty() -> when { - parameter.plugins.hasPlugin("com.android.library") -> SCOPE_PROJECT - parameter.plugins.hasPlugin("com.android.application") -> SCOPE_FULL_PROJECT - parameter.plugins.hasPlugin("com.android.dynamic-feature") -> SCOPE_FULL_WITH_FEATURES - else -> TODO("Not an Android project") - } - else -> super.getReferencedScopes() - } - - final override fun transform(invocation: TransformInvocation) { - BoosterTransformInvocation(invocation, this).apply { - if (isIncremental) { - doIncrementalTransform() - } else { - outputProvider?.deleteAll() - doFullTransform() - } - } - } - - companion object { - - fun newInstance(project: Project, name: String = "booster"): BoosterTransform { - val parameter = project.newTransformParameter(name) - return when { - GTE_V3_4 -> BoosterTransformV34(parameter) - else -> BoosterTransform(parameter) - } - } - - } - -} - -/** - * The option for transform outputs verifying, default is false - */ -private const val OPT_TRANSFORM_VERIFY = "booster.transform.verify" diff --git a/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/BoosterTransformInvocation.kt b/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/BoosterTransformInvocation.kt deleted file mode 100644 index 93e32c594..000000000 --- a/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/BoosterTransformInvocation.kt +++ /dev/null @@ -1,275 +0,0 @@ -package com.didiglobal.booster.gradle - -import com.android.build.api.transform.DirectoryInput -import com.android.build.api.transform.Format -import com.android.build.api.transform.JarInput -import com.android.build.api.transform.QualifiedContent -import com.android.build.api.transform.Status.NOTCHANGED -import com.android.build.api.transform.Status.REMOVED -import com.android.build.api.transform.TransformInvocation -import com.android.build.gradle.BaseExtension -import com.android.dex.DexFormat -import com.didiglobal.booster.gradle.util.dex -import com.didiglobal.booster.kotlinx.NCPU -import com.didiglobal.booster.kotlinx.file -import com.didiglobal.booster.kotlinx.green -import com.didiglobal.booster.kotlinx.red -import com.didiglobal.booster.transform.AbstractKlassPool -import com.didiglobal.booster.transform.ArtifactManager -import com.didiglobal.booster.transform.Collector -import com.didiglobal.booster.transform.TransformContext -import com.didiglobal.booster.transform.Transformer -import com.didiglobal.booster.transform.artifacts -import com.didiglobal.booster.transform.util.CompositeCollector -import com.didiglobal.booster.transform.util.collect -import com.didiglobal.booster.transform.util.transform -import org.apache.commons.codec.digest.DigestUtils.md5Hex -import java.io.File -import java.net.URI -import java.util.concurrent.Callable -import java.util.concurrent.CopyOnWriteArrayList -import java.util.concurrent.ExecutorService -import java.util.concurrent.Executors -import java.util.concurrent.Future -import java.util.concurrent.TimeUnit - -/** - * Represents a delegate of TransformInvocation - * - * @author johnsonlee - */ -internal class BoosterTransformInvocation( - private val delegate: TransformInvocation, - private val transform: BoosterTransform -) : TransformInvocation by delegate, TransformContext, ArtifactManager { - - private val outputs = CopyOnWriteArrayList() - - private val collectors = CopyOnWriteArrayList>() - - /* - * Preload transformers as List to fix NoSuchElementException caused by ServiceLoader in parallel mode - */ - private val transformers: List = transform.parameter.transformers.map { - try { - it.getConstructor(ClassLoader::class.java).newInstance(transform.parameter.buildscript.classLoader) - } catch (e1: Throwable) { - try { - it.getConstructor().newInstance() - } catch (e2: Throwable) { - throw e2.apply { - addSuppressed(e1) - } - } - } - } - - override val name: String = delegate.context.variantName - - override val projectDir: File = project.projectDir - - override val buildDir: File = project.buildDir - - override val temporaryDir: File = delegate.context.temporaryDir - - override val reportsDir: File = File(buildDir, "reports").also { it.mkdirs() } - - override val bootClasspath = delegate.bootClasspath - - override val compileClasspath = delegate.compileClasspath - - override val runtimeClasspath = delegate.runtimeClasspath - - override val artifacts = this - - override val dependencies: Collection by lazy { - ResolvedArtifactResults(variant).map { - it.id.displayName - } - } - - private val bootKlassPool by lazy { - object : AbstractKlassPool(project.getAndroid().bootClasspath) {} - } - - override val klassPool by lazy { - object : AbstractKlassPool(compileClasspath, bootKlassPool) {} - } - - override val applicationId = delegate.applicationId - - override val originalApplicationId = delegate.originalApplicationId - - override val isDebuggable = variant.buildType.isDebuggable - - override val isDataBindingEnabled = delegate.isDataBindingEnabled - - override fun hasProperty(name: String) = project.hasProperty(name) - - override fun getProperty(name: String, default: T): T = project.getProperty(name, default) - - override fun get(type: String) = variant.artifacts.get(type) - - override fun registerCollector(collector: Collector) { - this.collectors += collector - } - - override fun unregisterCollector(collector: Collector) { - this.collectors -= collector - } - - internal fun doFullTransform() = doTransform(this::transformFully) - - internal fun doIncrementalTransform() = doTransform(this::transformIncrementally) - - private fun lookAhead(executor: ExecutorService): Set { - return this.inputs.asSequence().map { - it.jarInputs + it.directoryInputs - }.flatten().map { input -> - executor.submit(Callable { - input.file.takeIf { file -> - file.collect(CompositeCollector(collectors)).isNotEmpty() - } - }) - }.mapNotNull { - it.get() - }.toSet() - } - - private fun onPreTransform() { - transformers.forEach { - it.onPreTransform(this) - } - } - - private fun onPostTransform() { - transformers.forEach { - it.onPostTransform(this) - } - } - - private fun doTransform(block: (ExecutorService, Set) -> Iterable>) { - this.outputs.clear() - this.collectors.clear() - - val executor = Executors.newFixedThreadPool(NCPU) - - this.onPreTransform() - - // Look ahead to determine which input need to be transformed even incremental build - val outOfDate = this.lookAhead(executor).onEach { - project.logger.info("✨ ${it.canonicalPath} OUT-OF-DATE ") - } - - try { - block(executor, outOfDate).forEach { - it.get() - } - } finally { - executor.shutdown() - executor.awaitTermination(1, TimeUnit.HOURS) - } - - this.onPostTransform() - - if (transform.verifyEnabled) { - this.doVerify() - } - } - - private fun transformFully(executor: ExecutorService, @Suppress("UNUSED_PARAMETER") outOfDate: Set) = this.inputs.map { - it.jarInputs + it.directoryInputs - }.flatten().map { input -> - executor.submit { - val format = if (input is DirectoryInput) Format.DIRECTORY else Format.JAR - outputProvider?.let { provider -> - input.transform(provider.getContentLocation(input.id, input.contentTypes, input.scopes, format)) - } - } - } - - private fun transformIncrementally(executor: ExecutorService, outOfDate: Set) = this.inputs.map { input -> - input.jarInputs.filter { - it.status != NOTCHANGED || outOfDate.contains(it.file) - }.map { jarInput -> - executor.submit { - doIncrementalTransform(jarInput) - } - } + input.directoryInputs.filter { - it.changedFiles.isNotEmpty() || outOfDate.contains(it.file) - }.map { dirInput -> - executor.submit { - doIncrementalTransform(dirInput, dirInput.file.toURI()) - } - } - }.flatten() - - @Suppress("NON_EXHAUSTIVE_WHEN") - private fun doIncrementalTransform(jarInput: JarInput) { - when (jarInput.status) { - REMOVED -> { - outputProvider?.getContentLocation(jarInput.id, jarInput.contentTypes, jarInput.scopes, Format.JAR)?.takeIf { - it.exists() - }?.delete() - } - else -> { - outputProvider?.let { provider -> - jarInput.transform(provider.getContentLocation(jarInput.id, jarInput.contentTypes, jarInput.scopes, Format.JAR)) - } - } - } - } - - @Suppress("NON_EXHAUSTIVE_WHEN") - private fun doIncrementalTransform(dirInput: DirectoryInput, base: URI) { - dirInput.changedFiles.forEach { (file, status) -> - when (status) { - REMOVED -> { - outputProvider?.let { provider -> - provider.getContentLocation(dirInput.id, dirInput.contentTypes, dirInput.scopes, Format.DIRECTORY).parentFile.listFiles()?.asSequence() - ?.filter { it.isDirectory } - ?.map { File(it, dirInput.file.toURI().relativize(file.toURI()).path) } - ?.filter { it.exists() } - ?.forEach { it.delete() } - } - file.delete() - } - else -> { - outputProvider?.let { provider -> - val root = provider.getContentLocation(dirInput.id, dirInput.contentTypes, dirInput.scopes, Format.DIRECTORY) - val output = File(root, base.relativize(file.toURI()).path) - file.transform(output) - } - } - } - } - } - - private fun doVerify() { - outputs.sortedBy(File::nameWithoutExtension).forEach { input -> - val output = temporaryDir.file(input.name) - val rc = input.dex(output, targetSdkVersion.apiLevel) - println("${if (rc != 0) red("✗") else green("✓")} $input") - output.deleteRecursively() - } - } - - private val QualifiedContent.id: String - get() = md5Hex(file.absolutePath) - - private fun QualifiedContent.transform(output: File) = this.file.transform(output) - - private fun File.transform(output: File) { - outputs += output - project.logger.info("Booster transforming $this => $output") - this.transform(output) { bytecode -> - bytecode.transform() - } - } - - private fun ByteArray.transform(): ByteArray { - return transformers.fold(this) { bytes, transformer -> - transformer.transform(this@BoosterTransformInvocation, bytes) - } - } -} diff --git a/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/BoosterTransformTask.kt b/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/BoosterTransformTask.kt new file mode 100644 index 000000000..9a432c4f9 --- /dev/null +++ b/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/BoosterTransformTask.kt @@ -0,0 +1,221 @@ +package com.didiglobal.booster.gradle + +import com.android.build.api.variant.Variant +import com.didiglobal.booster.kotlinx.NCPU +import com.didiglobal.booster.kotlinx.search +import com.didiglobal.booster.kotlinx.touch +import com.didiglobal.booster.transform.AbstractTransformContext +import com.didiglobal.booster.transform.Transformer +import com.didiglobal.booster.transform.artifactManager +import com.didiglobal.booster.transform.util.CompositeCollector +import com.didiglobal.booster.transform.util.collect +import com.google.common.collect.Sets +import org.apache.commons.compress.archivers.jar.JarArchiveEntry +import org.apache.commons.compress.archivers.jar.JarArchiveOutputStream +import org.apache.commons.compress.archivers.zip.ParallelScatterZipCreator +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry +import org.apache.commons.compress.parallel.InputStreamSupplier +import org.gradle.api.DefaultTask +import org.gradle.api.file.Directory +import org.gradle.api.file.RegularFile +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.OutputFile +import org.gradle.api.tasks.TaskAction +import java.io.File +import java.io.IOException +import java.util.concurrent.Executors +import java.util.concurrent.LinkedBlockingQueue +import java.util.concurrent.ThreadPoolExecutor +import java.util.concurrent.TimeUnit +import java.util.zip.ZipEntry +import java.util.zip.ZipInputStream + +abstract class BoosterTransformTask : DefaultTask() { + + @get:Input + abstract var applicationId: String + + @get:Internal + abstract var transformers: Collection + + @get:Internal + abstract var variant: Variant + + @get:Internal + abstract var bootClasspath: Provider> + + @get:InputFiles + abstract val allJars: ListProperty + + @get:InputFiles + abstract val allDirectories: ListProperty + + @get:OutputFile + abstract val output: RegularFileProperty + + private val entries = Sets.newConcurrentHashSet() + + @TaskAction + fun taskAction() { + val context = object : AbstractTransformContext( + applicationId, + variant.name, + bootClasspath.get().map(RegularFile::getAsFile), + compileClasspath, + compileClasspath + ) { + override val projectDir = project.projectDir + override val artifacts = variant.artifactManager + } + val executor = Executors.newFixedThreadPool(NCPU) + try { + transformers.map { + executor.submit { + it.onPreTransform(context) + } + }.forEach { + it.get() + } + + compileClasspath.map { input -> + executor.submit { + input.takeIf { + it.collect(CompositeCollector(context.collectors)).isNotEmpty() + } + } + }.forEach { + it.get() + } + JarArchiveOutputStream(output.get().asFile.touch().outputStream().buffered()).use { jos -> + val creator = ParallelScatterZipCreator( + ThreadPoolExecutor( + NCPU, + NCPU, + 0L, + TimeUnit.MILLISECONDS, + LinkedBlockingQueue(), + Executors.defaultThreadFactory() + ) { runnable, _ -> + runnable.run() + } + ) + + compileClasspath.map { + executor.submit { + it.transform("", creator) { bytecode -> + transformers.fold(bytecode) { bytes, transformer -> + transformer.transform(context, bytes) + } + } + } + }.forEach { + it.get() + } + creator.writeTo(jos) + } + + transformers.map { + executor.submit { + it.onPostTransform(context) + } + }.forEach { + it.get() + } + } finally { + executor.shutdown() + executor.awaitTermination(1L, TimeUnit.HOURS) + } + } + + private val compileClasspath: Collection + get() = (allJars.get() + allDirectories.get()).map { + it.asFile + } + + + /** + * Transform this file or directory to the output by the specified transformer + * + * @param transformer The byte data transformer + */ + fun File.transform( + prefix: String, + creator: ParallelScatterZipCreator, + transformer: (ByteArray) -> ByteArray = { it -> it } + ) { + when { + isDirectory -> { + this.toURI().let { base -> + this.search { + it.extension.lowercase() == "class" + }.parallelStream().forEach { + it.transform(creator, base.relativize(it.toURI()).path, transformer) + } + } + } + + isFile -> when (extension.lowercase()) { + "jar" -> ZipInputStream(this.inputStream()).use { + it.transform(creator, ::JarArchiveEntry, transformer) + } + + "class" -> transform(creator, "$prefix/$name".substring(1), transformer) + else -> println("Not transform file $path") + } + + else -> throw IOException("Unexpected file: ${this.canonicalPath}") + } + } + + fun File.transform(creator: ParallelScatterZipCreator, name: String, transformer: (ByteArray) -> ByteArray) { + if (entries.contains(name)) { + return + } + this.inputStream().use { + val inputStreamSupplier = { + transformer(readBytes()).inputStream() + } + val jarArchiveEntry = JarArchiveEntry(name).apply { + method = JarArchiveEntry.DEFLATED + } + creator.addArchiveEntry(jarArchiveEntry, inputStreamSupplier) + } + entries.add(name) + } + + fun ZipInputStream.transform( + creator: ParallelScatterZipCreator, + entryFactory: (ZipEntry) -> ZipArchiveEntry = ::ZipArchiveEntry, + transformer: (ByteArray) -> ByteArray + ) { + while (true) { + val next = nextEntry ?: break + val entry = next.takeIf(::isValidate) ?: continue + if (!entries.contains(entry.name)) { + entries.add(entry.name) + val zae = entryFactory(entry) + val data = readBytes() + val stream = InputStreamSupplier { + if (entry.isDirectory) { + data.inputStream() + } else { + transformer(data).inputStream() + } + } + creator.addArchiveEntry(zae, stream) + } + } + } + + + private fun isValidate(entry: ZipEntry): Boolean { + return (entry.isDirectory || entry.name.endsWith(".class")) && !entry.name.startsWith("META-INF/") + } +} + + diff --git a/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/BoosterTransformTaskExecutionListener.kt b/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/BoosterTransformTaskExecutionListener.kt deleted file mode 100644 index a8de0efda..000000000 --- a/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/BoosterTransformTaskExecutionListener.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.didiglobal.booster.gradle - -import com.android.build.gradle.internal.pipeline.TransformTask -import com.didiglobal.booster.kotlinx.call -import com.didiglobal.booster.kotlinx.get -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.execution.TaskExecutionAdapter - -/** - * Only for AGP version lower than 3.6.0 - * - * @author neighbWang - */ -class BoosterTransformTaskExecutionListener(private val project: Project) : TaskExecutionAdapter() { - - override fun beforeExecute(task: Task) { - task.takeIf { - it.project == project && it is TransformTask && it.transform.scopes.isNotEmpty() - }?.run { - task["outputStream"]?.call("init") - } - } - -} \ No newline at end of file diff --git a/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/ServiceLoader.kt b/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/ServiceLoader.kt index 6f7a0e3e5..d108fefd1 100644 --- a/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/ServiceLoader.kt +++ b/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/ServiceLoader.kt @@ -73,6 +73,14 @@ internal fun loadVariantProcessors(project: Project): List { return newServiceLoader(project.buildscript.classLoader, Project::class.java).load(project) } +/** + * Load [VariantProcessor]s with the specified [variant] + */ +@Throws(ServiceConfigurationError::class) +internal fun loadTransformers(classLoader: ClassLoader): List { + return newServiceLoader(classLoader, ClassLoader::class.java).load(classLoader) +} + @Throws(ServiceConfigurationError::class) private fun parse(u: URL) = try { u.openStream().bufferedReader(StandardCharsets.UTF_8).readLines().filter { diff --git a/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/TransformParameter.kt b/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/TransformParameter.kt deleted file mode 100644 index 86a87f172..000000000 --- a/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/TransformParameter.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.didiglobal.booster.gradle - -import com.didiglobal.booster.transform.Transformer -import org.gradle.api.Project -import org.gradle.api.initialization.dsl.ScriptHandler -import org.gradle.api.plugins.PluginContainer -import java.io.Serializable - -data class TransformParameter( - val name: String, - val buildscript: ScriptHandler, - val plugins: PluginContainer, - val properties: Map, - val transformers: Set> -) : Serializable - -fun Project.newTransformParameter(name: String): TransformParameter { - return TransformParameter(name, buildscript, plugins, properties, lookupTransformers(buildscript.classLoader)) -} \ No newline at end of file diff --git a/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/internal/BoosterTransformV34.kt b/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/internal/BoosterTransformV34.kt deleted file mode 100644 index 68db710df..000000000 --- a/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/internal/BoosterTransformV34.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.didiglobal.booster.gradle.internal - -import com.android.build.api.variant.VariantInfo -import com.didiglobal.booster.gradle.BoosterTransform -import com.didiglobal.booster.gradle.TransformParameter - -internal class BoosterTransformV34(parameter: TransformParameter) : BoosterTransform(parameter) { - - @Suppress("UnstableApiUsage") - override fun applyToVariant(variant: VariantInfo): Boolean { - return variant.buildTypeEnabled || (variant.flavorNames.isNotEmpty() && variant.fullVariantEnabled) - } - - @Suppress("UnstableApiUsage") - private val VariantInfo.fullVariantEnabled: Boolean - get() = parameter.properties["booster.transform.${fullVariantName}.enabled"]?.toString()?.toBoolean() ?: true - - @Suppress("UnstableApiUsage") - private val VariantInfo.buildTypeEnabled: Boolean - get() = parameter.properties["booster.transform.${buildTypeName}.enabled"]?.toString()?.toBoolean() ?: true - -} - diff --git a/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/util/Dexer.kt b/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/util/Dexer.kt deleted file mode 100644 index bad4dcaa0..000000000 --- a/booster-gradle-plugin/src/main/kotlin/com/didiglobal/booster/gradle/util/Dexer.kt +++ /dev/null @@ -1,63 +0,0 @@ -package com.didiglobal.booster.gradle.util - -import com.android.dex.DexFormat -import com.android.dx.command.dexer.Main -import com.android.tools.r8.D8 -import com.didiglobal.booster.gradle.GTE_V7_X -import com.didiglobal.booster.kotlinx.NCPU -import com.didiglobal.booster.kotlinx.search -import com.didiglobal.booster.kotlinx.touch -import java.io.File - -internal fun File.dex(output: File, api: Int = DexFormat.API_NO_EXTENDED_OPCODES): Int { - return if (GTE_V7_X) { - runD8(this, output, api) - } else { - runDx(this, output, api) - } -} - -private fun runD8(input: File, output: File, api: Int): Int { - val inputs = when { - input.isDirectory -> { - output.mkdirs() - input.search { - it.extension.equals("class", true) - } - } - else -> { - output.touch() - listOf(input) - } - } - - val args = inputs.map { it.canonicalPath } + "--min-api" + api.toString() - return try { - D8.main(args.toTypedArray()) - 0 - } catch (t: Throwable) { - t.printStackTrace() - -1 - } -} - -private fun runDx(input: File, output: File, api: Int): Int { - val args = Main.Arguments().apply { - numThreads = NCPU - debug = true - warnings = true - emptyOk = true - multiDex = true - jarOutput = true - optimize = false - minSdkVersion = api - fileNames = arrayOf(input.canonicalPath) - outName = output.canonicalPath - } - return try { - Main.run(args) - } catch (t: Throwable) { - t.printStackTrace() - -1 - } -} diff --git a/booster-kotlinx/src/main/kotlin/com/didiglobal/booster/kotlinx/text.kt b/booster-kotlinx/src/main/kotlin/com/didiglobal/booster/kotlinx/text.kt index 4d004cd39..59064ca95 100644 --- a/booster-kotlinx/src/main/kotlin/com/didiglobal/booster/kotlinx/text.kt +++ b/booster-kotlinx/src/main/kotlin/com/didiglobal/booster/kotlinx/text.kt @@ -3,6 +3,7 @@ package com.didiglobal.booster.kotlinx import java.io.File import java.math.BigInteger import java.security.MessageDigest +import java.util.Locale import java.util.regex.Pattern private val PATTERN_JAVA_IDENTIFIER = Pattern.compile("[a-zA-Z_\$][a-zA-Z\\d_\$]*") @@ -24,3 +25,7 @@ fun String.matches(wildcard: Wildcard): Boolean { } fun String.isValidJavaIdentifier(): Boolean = PATTERN_JAVA_IDENTIFIER.matcher(this).matches() + +fun String.capitalized(): String = replaceFirstChar { + if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() +} diff --git a/booster-task-analyser/README.md b/booster-task-analyser/README.md deleted file mode 100644 index 2710540e5..000000000 --- a/booster-task-analyser/README.md +++ /dev/null @@ -1,78 +0,0 @@ -# booster-task-analyser - -This module is used for static analysing. - -## Performance Analysis - -Start performance analysis by executing the following command - -```bash -./gradlew analysePerformanceDebug -``` - -or - -```bash -./gradlew analysePerformanceRelease -``` - -or - -```bash -./gradlew analysePerformance -``` - -### Analyser Reports - -The [dot](https://www.graphviz.org/doc/info/lang.html) format reports is located at `build/reports/${variant}/booster-task-analyser/`, you can convert the dot files to PNGs by using the following command: - -```bash -find build/reports -name '*.dot' | xargs -t -I{} dot -O -Tpng {} -``` - -Here is an example generated by dot: - -![com.didiglobal.booster.demo.MainActivity](../assets/com.didiglobal.booster.demo.MainActivity.dot.png) - -## Properties - -The following table shows the properties that analyser supports: - -| Property | Description | Example | -| -------------------------------- | --------------------------------------------------------------------------------------------- | ----------------------------------- | -| `booster.task.analyser.blacklist` | URI of API black list(Using [built-in API list](src/main/resources/blacklist.txt) by default)| file:///Users/booster/blacklist.txt | -| `booster.task.analyser.whitelist` | URI of API white list(Using [built-in API list](src/main/resources/whitelist.txt) by default)| file:///Users/booster/whitelist.txt | - -The properties can be passthrough the command line as following: - -```bash -./gradlew assembleDebug -Pbooster.task.analyser.whitelist=file:///Users/booster/whitelist.txt -``` - -or configured in the `gradle.properties`: - -```properties -booster.task.analyser.whitelist=file:///Users/booster/whitelist.txt -``` - -## Reference Analysis - -Start reference analysis by executing the following command - -```bash -./gradlew analyseReferenceDebug -``` - -or - -```bash -./gradlew analyseReferenceRelease -``` - -or - -```bash -./gradlew analyseReference -``` - -The reports are located at `build/reports/booster-task-analyser/reference/` diff --git a/booster-task-analyser/build.gradle b/booster-task-analyser/build.gradle deleted file mode 100644 index 04ca913fc..000000000 --- a/booster-task-analyser/build.gradle +++ /dev/null @@ -1,13 +0,0 @@ -apply from: "$rootDir/gradle/booster.gradle" - -dependencies { - kapt "com.google.auto.service:auto-service:1.0" - implementation project(':booster-aapt2') - implementation project(':booster-api') - implementation project(':booster-cha-asm') - implementation project(':booster-graph-dot') - implementation project(':booster-graph-json') - implementation project(':booster-transform-asm') - compileOnly 'com.android.tools.build:gradle:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' -} diff --git a/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/AnalysisTask.kt b/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/AnalysisTask.kt deleted file mode 100644 index 513ed3942..000000000 --- a/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/AnalysisTask.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.didiglobal.booster.task.analyser - -import com.android.build.gradle.api.BaseVariant -import com.didiglobal.booster.BOOSTER -import com.didiglobal.booster.cha.asm.AsmClassSetCache -import com.didiglobal.booster.kotlinx.touch -import org.gradle.api.DefaultTask -import org.gradle.api.tasks.Internal -import java.io.File - -abstract class AnalysisTask : DefaultTask() { - - @get:Internal - var variant: BaseVariant? = null - - @get:Internal - lateinit var classSetCache: AsmClassSetCache - - @Internal - final override fun getGroup(): String = BOOSTER - - @Internal - abstract override fun getDescription(): String - - abstract fun analyse() - -} - -internal val AnalysisTask.reportDir: File - get() = project.buildDir - .resolve("reports") - .resolve(Build.ARTIFACT) - .resolve(javaClass.kotlin.category) - .resolve(variant?.dirName ?: ".") - -internal fun AnalysisTask.report(name: String): File { - return reportDir.resolve(name).resolve("index.${name}").touch() -} diff --git a/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/AnalysisVariantProcessor.kt b/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/AnalysisVariantProcessor.kt deleted file mode 100644 index f34022275..000000000 --- a/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/AnalysisVariantProcessor.kt +++ /dev/null @@ -1,83 +0,0 @@ -package com.didiglobal.booster.task.analyser - -import com.android.build.gradle.AppExtension -import com.android.build.gradle.BaseExtension -import com.android.build.gradle.LibraryExtension -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.internal.tasks.factory.dependsOn -import com.didiglobal.booster.cha.asm.AsmClassSetCache -import com.didiglobal.booster.gradle.getAndroidOrNull -import com.didiglobal.booster.gradle.getJarTaskProviders -import com.didiglobal.booster.gradle.getTaskName -import com.didiglobal.booster.gradle.getUpstreamProjects -import com.didiglobal.booster.gradle.isAndroid -import com.didiglobal.booster.gradle.isJava -import com.didiglobal.booster.gradle.isJavaLibrary -import com.didiglobal.booster.gradle.project -import com.didiglobal.booster.task.analyser.performance.PerformanceAnalysisTask -import com.didiglobal.booster.task.analyser.reference.ReferenceAnalysisTask -import com.didiglobal.booster.task.spi.VariantProcessor -import com.google.auto.service.AutoService -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.UnknownTaskException -import org.gradle.api.tasks.TaskProvider -import java.util.Locale -import kotlin.reflect.KClass - -@AutoService(VariantProcessor::class) -class AnalysisVariantProcessor : VariantProcessor { - - private val classSetCache = AsmClassSetCache() - - override fun process(variant: BaseVariant) { - variant.project.gradle.projectsEvaluated { gradle -> - gradle.rootProject.allprojects { - it.setup() - } - } - } - - private fun Project.setup() { - when { - isAndroid -> { - setupAndroid() - setupAndroid() - } - isJavaLibrary || isJava -> { - setupTasks() - } - } - } - - private inline fun Project.setupTasks(variant: BaseVariant? = null): TaskProvider { - val taskName = variant?.getTaskName(T::class.taskName) ?: T::class.taskName - return try { - tasks.named(taskName) - } catch (e: UnknownTaskException) { - tasks.register(taskName, T::class.java) { - it.variant = variant - it.classSetCache = classSetCache - }.dependsOn(getUpstreamProjects(false, variant).plus(this).map { - it.getJarTaskProviders(variant) - }.flatten()) - } - } - - private inline fun Project.setupAndroid() { - when (val android = getAndroidOrNull()) { - is LibraryExtension -> android.libraryVariants - is AppExtension -> android.applicationVariants - else -> emptyList() - }.map { - setupTasks(it) - } - } - -} - -internal inline val KClass.category: String - get() = T::class.java.simpleName.substringBefore(AnalysisTask::class.java.simpleName).lowercase() - -internal inline val KClass.taskName: String - get() = @Suppress("DEPRECATION") "analyse${category.capitalize()}" diff --git a/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/performance/LayoutHandler.kt b/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/performance/LayoutHandler.kt deleted file mode 100644 index 92ed8ec00..000000000 --- a/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/performance/LayoutHandler.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.didiglobal.booster.task.analyser.performance - -import org.xml.sax.Attributes -import org.xml.sax.helpers.DefaultHandler - -/** - * @author johnsonlee - */ -class LayoutHandler : DefaultHandler() { - - val views = mutableSetOf() - - override fun startElement(uri: String, localName: String, qName: String, attributes: Attributes) { - views += qName - } - -} \ No newline at end of file diff --git a/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/performance/PerformanceAnalyser.kt b/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/performance/PerformanceAnalyser.kt deleted file mode 100644 index eee88b6a8..000000000 --- a/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/performance/PerformanceAnalyser.kt +++ /dev/null @@ -1,454 +0,0 @@ -package com.didiglobal.booster.task.analyser.performance - -import com.didiglobal.booster.aapt2.metadata -import com.didiglobal.booster.cha.ClassHierarchy -import com.didiglobal.booster.cha.ClassSet -import com.didiglobal.booster.cha.JAVA_LANG_OBJECT -import com.didiglobal.booster.cha.asm.from -import com.didiglobal.booster.cha.fold -import com.didiglobal.booster.cha.graph.CallNode -import com.didiglobal.booster.cha.graph.ROOT -import com.didiglobal.booster.graph.Graph -import com.didiglobal.booster.graph.dot.DotGraph -import com.didiglobal.booster.kotlinx.NCPU -import com.didiglobal.booster.kotlinx.asIterable -import com.didiglobal.booster.kotlinx.file -import com.didiglobal.booster.kotlinx.green -import com.didiglobal.booster.kotlinx.red -import com.didiglobal.booster.kotlinx.search -import com.didiglobal.booster.kotlinx.separatorsToSystem -import com.didiglobal.booster.kotlinx.yellow -import com.didiglobal.booster.task.analyser.Build -import com.didiglobal.booster.transform.ArtifactManager -import com.didiglobal.booster.transform.asm.args -import com.didiglobal.booster.transform.asm.className -import com.didiglobal.booster.transform.asm.getValue -import com.didiglobal.booster.transform.asm.isAbstract -import com.didiglobal.booster.transform.asm.isAnnotation -import com.didiglobal.booster.transform.asm.isInterface -import com.didiglobal.booster.transform.asm.isInvisibleAnnotationPresent -import com.didiglobal.booster.transform.asm.isNative -import com.didiglobal.booster.transform.asm.isProtected -import com.didiglobal.booster.transform.asm.isPublic -import com.didiglobal.booster.transform.asm.isStatic -import com.didiglobal.booster.transform.util.ComponentHandler -import org.objectweb.asm.tree.ClassNode -import org.objectweb.asm.tree.MethodInsnNode -import org.objectweb.asm.tree.MethodNode -import java.io.File -import java.net.URL -import java.util.concurrent.Callable -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.CopyOnWriteArraySet -import java.util.concurrent.ExecutorService -import java.util.concurrent.Executors -import java.util.concurrent.Future -import java.util.concurrent.TimeUnit -import java.util.concurrent.atomic.AtomicInteger -import javax.xml.parsers.SAXParserFactory -import kotlin.collections.component1 -import kotlin.collections.component2 -import kotlin.collections.set -import kotlin.streams.toList - -/** - * @author johnsonlee - */ -class PerformanceAnalyser( - private val providedClasspath: Collection, - private val compileClasspath: Collection, - private val artifacts: ArtifactManager, - private val properties: Map = emptyMap() -) { - - private val providedClasses = providedClasspath.map { - ClassSet.from(it) - }.fold() - - private val compileClasses = compileClasspath.map { - ClassSet.from(it) - }.fold() - - private val classes = providedClasses + compileClasses - - private val unresolvedClasses = mutableSetOf() - - private val hierarchy = ClassHierarchy(classes) { - unresolvedClasses += it - } - - /** - * The global call graph of whole project - */ - private val globalBuilder = Graph.Builder() - - /** - * The call graph of each class - */ - private val graphBuilders = ConcurrentHashMap>() - - private val classesRunOnUiThread = ConcurrentHashMap() - private val classesRunOnMainThread = ConcurrentHashMap() - - private val nodesRunOnUiThread = CopyOnWriteArraySet(PLATFORM_METHODS_RUN_ON_UI_THREAD) - private val nodesRunOnMainThread = CopyOnWriteArraySet(PLATFORM_METHODS_RUN_ON_MAIN_THREAD) - - private val blacklist = URL(properties[PROPERTY_BLACKLIST]?.toString() ?: VALUE_BLACKLIST).openStream().bufferedReader().use { - it.readLines().filter(String::isNotBlank).map(CallNode.Companion::valueOf).toSet() - } - - private val whitelist = URL(properties[PROPERTY_WHITELIST]?.toString() ?: VALUE_WHITELIST).openStream().bufferedReader().use { - it.readLines().filter(String::isNotBlank).map(CallNode.Companion::valueOf).toSet() - } - - private val mainThreadAnnotations: Set by lazy { - MAIN_THREAD_ANNOTATIONS.filter(classes::contains).map(::descriptor).toSet() - } - - private val uiThreadAnnotations: Set by lazy { - UI_THREAD_ANNOTATIONS.filter(classes::contains).map(::descriptor).toSet() - } - - constructor(platform: File, compileClasspath: Collection, artifacts: ArtifactManager, properties: Map = emptyMap()) - : this(platform.bootClasspath, compileClasspath, artifacts, properties) - - fun analyse(output: File) { - this.classes.load().use { - this.loadEntryPoints() - this.analyse() - this.dump(output) - this.unresolvedClasses.forEach { - println("Unresolved class ${red(it.replace('/', '.'))}") - } - } - } - - private fun analyse() { - val classes = this.compileClasses.parallelStream().filter(ClassNode::isInclude).toList() - val index = AtomicInteger(0) - val count = classes.size - val executor = Executors.newFixedThreadPool(NCPU) - - try { - classes.map { - executor.submit { - val t0 = System.currentTimeMillis() - this.analyse(it) - println("${green(String.format("%3d%%", index.incrementAndGet() * 100 / count))} Analyse class ${it.className} in ${yellow(System.currentTimeMillis() - t0)} ms") - } - }.forEach { - it.get() - } - } finally { - executor.shutdown() - executor.awaitTermination(1L, TimeUnit.HOURS) - } - } - - private fun loadEntryPoints() { - val executor = Executors.newFixedThreadPool(NCPU) - - try { - (loadMainThreadEntryPoints(executor) + loadUiThreadEntryPoints(executor)).forEach { - it.get() - } - } finally { - executor.shutdown() - executor.awaitTermination(1L, TimeUnit.HOURS) - } - } - - /** - * Find main thread entry point by parsing AndroidManifest.xml - */ - private fun loadMainThreadEntryPoints(executor: ExecutorService): List> { - val handler = this.artifacts.get(ArtifactManager.MERGED_MANIFESTS).map { manifest -> - ComponentHandler().also { handler -> - SAXParserFactory.newInstance().newSAXParser().parse(manifest, handler) - } - }.fold(ComponentHandler()) { acc, i -> - acc.applications += i.applications - acc.activities += i.activities - acc.services += i.services - acc.receivers += i.receivers - acc.providers += i.providers - acc - } - - return arrayOf( - "android/app/Application" to handler.applications, - "android/app/Activity" to handler.activities, - "android/app/Service" to handler.services, - "android/content/BroadcastReceiver" to handler.receivers, - "android/content/ContentProvider" to handler.providers - ).map { - executor.submit(Callable, Collection>> { - val clazz = this.hierarchy[it.first] ?: throw ClassNotFoundException(it.first.replace('/', '.')) - Triple(clazz, it.second.map { it.replace('.', '/') }, clazz.methods.filter(MethodNode::isEntryPoint)) - }) - }.map { future -> - val (clazz, components, entryPoints) = future.get() - - classesRunOnMainThread[clazz.name] = clazz - - components.map { component -> - executor.submit { - println("Loading main thread entry points from $component ...") - - val nodes = entryPoints.map { - CallNode(clazz.name, it.name, it.desc) - } - - this.hierarchy[component]?.run { - classesRunOnMainThread[component] = this - } - this.globalBuilder.addEdges(ROOT, nodes) - this.nodesRunOnMainThread += nodes - } - } - }.flatten() - } - - /** - * Find custom View as UI thread entry point by parsing layout xml - */ - private fun loadUiThreadEntryPoints(executor: ExecutorService): List> { - // Load platform widgets - val widgets = this.providedClasspath.find { - it.name == "android.jar" - }?.parentFile?.file("data", "widgets.txt")?.readLines()?.filter { - it.startsWith("W") - }?.map { - it.substring(1, it.indexOf(' ')) - }?.toSet() ?: emptySet() - - val visit: (File) -> Set = { xml -> - val handler = LayoutHandler() - SAXParserFactory.newInstance().newSAXParser().parse(xml, handler) - handler.views - } - - return this.artifacts.get(ArtifactManager.MERGED_RES).search { - it.name.startsWith("layout_") && it.name.endsWith(".xml.flat") - }.map { flat -> - executor.submit { - val header = flat.metadata - val xml = header.sourceFile - - println("Parsing ${header.resourcePath} ...") - - this.nodesRunOnUiThread += visit(xml).filter { - '.' in it || it in widgets // ignore system widgets - }.map { tag -> - val desc = tag.replace('.', '/') - val clazz = this.hierarchy[desc] - - if (null == clazz) { - println(red("Unresolved class ${tag}: ${header.resourceName} -> ${header.sourcePath}")) - emptyList() - } else { - classesRunOnUiThread[desc] = clazz - - hierarchy.getSuperTypes(clazz).filter { - it.name != JAVA_LANG_OBJECT - }.forEach { - classesRunOnUiThread[it.name] = it - } - - val nodes = clazz.methods.filter(MethodNode::isEntryPoint).map { m -> - CallNode(clazz.name, m.name, m.desc) - } - - globalBuilder.addEdges(ROOT, nodes) - nodes - } - }.flatten() - } - } - } - - private fun analyse(clazz: ClassNode) { - val isClassRunOnUiThread = clazz.isRunOnUiThread() - val isClassRunOnMainThread = clazz.isRunOnMainThread() - val isClassRunOnUiOrMainThread = isClassRunOnMainThread || isClassRunOnUiThread - - clazz.methods.forEach { method -> - val isMethodRunUiOrMainThread = isClassRunOnUiOrMainThread - || method.isRunOnUiThread(clazz) - || method.isRunOnMainThread(clazz) - || method.isSubscribeOnMainThread() - - if (isMethodRunUiOrMainThread) { - val node = CallNode(clazz.name, method.name, method.desc) - - if (isClassRunOnMainThread) { - nodesRunOnMainThread += node - } - - if (isClassRunOnUiThread) { - nodesRunOnUiThread += node - } - - globalBuilder.addEdge(ROOT, node) - } - - // construct call graph by scanning INVOKE* instructions - method.instructions.iterator().asIterable().filterIsInstance(MethodInsnNode::class.java).forEach { invoke -> - val to = CallNode(invoke.owner, invoke.name, invoke.desc) - val from = CallNode(clazz.name, method.name, method.desc) - - // break circular invocation - if (!globalBuilder.hasEdge(to, from)) { - globalBuilder.addEdge(from, to) - } - } - } - } - - /** - * Rendering call graph as individual dot format - */ - private fun dump(output: File) { - val global = globalBuilder.build() - val executor = Executors.newFixedThreadPool(NCPU) - - println("Generating call graphs ...") - - // Analyse global call graph and separate each chain to individual graph - global[ROOT].map { node -> - executor.submit { - analyse(global, node, listOf(ROOT, node)) { chain -> - val builder = graphBuilders.getOrPut(node.type) { - Graph.Builder().setTitle(node.type.replace('/', '.')) - } - builder.addEdges(chain) - } - } - }.forEach { - it.get() - } - - try { - graphBuilders.map { (name, builder) -> - File(output, name.separatorsToSystem() + ".dot") to builder.build() - }.map { (dot, graph) -> - executor.submit { - DotGraph.DIGRAPH.visualize(graph, dot) { - if (it == ROOT) graph.title else it.toPrettyString() - } - } - }.forEach { - it.get() - } - } finally { - executor.shutdown() - executor.awaitTermination(1L, TimeUnit.HOURS) - } - } - - /** - * Analyse from *node* recursively - * - * @param node The entry point - * @param chain The call chain - */ - private fun analyse(graph: Graph, node: CallNode, chain: List, action: (List) -> Unit) { - if (node in whitelist) { - return - } - - graph[node].forEach loop@{ target -> - // break circular invocation - if (chain.contains(target)) { - return@loop - } - - val newChain = chain.plus(target) - if (target matches blacklist) { - action(newChain) - return@loop - } - - analyse(graph, target, newChain, action) - } - } - - /** - * Check if this class is run on main thread - */ - private fun ClassNode.isRunOnMainThread() = isRunOnThread(mainThreadAnnotations, classesRunOnMainThread) - - /** - * Check if this class is run on UI thread - */ - private fun ClassNode.isRunOnUiThread() = isRunOnThread(uiThreadAnnotations, classesRunOnUiThread) - - private fun ClassNode.isRunOnThread(annotations: Set, classesRunOnThread: MutableMap): Boolean { - return isInvisibleAnnotationPresent(annotations) || classesRunOnThread.containsKey(name) - } - - /** - * Check if this method is run on main thread - */ - private fun MethodNode.isRunOnMainThread(clazz: ClassNode) = isRunOnThread(clazz, mainThreadAnnotations, nodesRunOnMainThread) - - /** - * Check if this method is run on UI thread - */ - private fun MethodNode.isRunOnUiThread(clazz: ClassNode) = isRunOnThread(clazz, uiThreadAnnotations, nodesRunOnUiThread) - - private fun MethodNode.isRunOnThread(clazz: ClassNode, annotations: Set, nodesRunOnThread: Set): Boolean { - if (this.isInvisibleAnnotationPresent(annotations)) { - return true - } - - return nodesRunOnThread.any { - it.name == this.name && it.args == this.args && hierarchy.isInheritFrom(clazz, it.type) - } - } - - private infix fun CallNode.matches(apis: Collection) = apis.contains(this) || apis.any { - // only match type, name and args because of covariant return type is partially allowed since JDK 1.5 - // (overridden method can have different return type in sub-type) - this.name == it.name && this.args == it.args && hierarchy.isInheritFrom(this.type, it.type) - } -} - -private val File.bootClasspath: Collection - get() = listOf(resolve("android.jar"), resolve("optional").resolve("org.apache.http.legacy.jar")) - -internal fun MethodNode.isSubscribeOnMainThread(): Boolean { - return visibleAnnotations - ?.find { it.desc == EVENTBUS_SUBSCRIBE } - ?.getValue>("threadMode") - ?.contentEquals(arrayOf(EVENTBUS_THREAD_MODE, "MAIN")) ?: false -} - -/** - * Excludes classes with conditions: - * - * - class in the ignore list - * - annotation classes - * - class has no methods containing any *invoke* instruction - */ -private val ClassNode.isInclude: Boolean - get() = !(EXCLUDES matches name || isAnnotation || ((isInterface || isAbstract) && methods.none { !it.isAbstract })) - -private val MethodNode.isEntryPoint: Boolean - get() = (isPublic || isProtected) && !isNative && !isStatic - -private fun descriptor(name: String) = "L${name};" - -private const val EVENTBUS_SUBSCRIBE = "Lorg/greenrobot/eventbus/Subscribe;" -private const val EVENTBUS_THREAD_MODE = "Lorg/greenrobot/eventbus/ThreadMode;" - -private val PROPERTY_PREFIX = Build.ARTIFACT.replace('-', '.') - -private val PROPERTY_BLACKLIST = "$PROPERTY_PREFIX.blacklist" - -private val PROPERTY_WHITELIST = "$PROPERTY_PREFIX.whitelist" - -internal val VALUE_BLACKLIST = PerformanceAnalyser::class.java.classLoader.getResource("blacklist.txt")!!.toString() - -internal val VALUE_WHITELIST = PerformanceAnalyser::class.java.classLoader.getResource("whitelist.txt")!!.toString() - diff --git a/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/performance/PerformanceAnalysisTask.kt b/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/performance/PerformanceAnalysisTask.kt deleted file mode 100644 index ef94d5b62..000000000 --- a/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/performance/PerformanceAnalysisTask.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.didiglobal.booster.task.analyser.performance - -import com.didiglobal.booster.gradle.extension -import com.didiglobal.booster.gradle.getJars -import com.didiglobal.booster.gradle.getUpstreamProjects -import com.didiglobal.booster.task.analyser.AnalysisTask -import com.didiglobal.booster.task.analyser.reportDir -import com.didiglobal.booster.transform.artifacts -import org.gradle.api.tasks.TaskAction - -/** - * Represents a task for performance analysing - * - * @author johnsonlee - */ -open class PerformanceAnalysisTask : AnalysisTask() { - - override fun getDescription(): String = "Analyses performance issues for Android projects" - - @TaskAction - override fun analyse() { - val variant = requireNotNull(this.variant) - val classpath = project.getJars(variant) + project.getUpstreamProjects(true, variant).map { - it.getJars(variant) - }.flatten() - - PerformanceAnalyser( - variant.extension.bootClasspath, - classpath, - variant.artifacts, - project.properties - ).analyse(reportDir) - } - -} \ No newline at end of file diff --git a/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/performance/constants.kt b/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/performance/constants.kt deleted file mode 100644 index ce250b9d3..000000000 --- a/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/performance/constants.kt +++ /dev/null @@ -1,86 +0,0 @@ -package com.didiglobal.booster.task.analyser.performance - -import com.didiglobal.booster.cha.graph.CallNode - -private const val DOLLAR = '$' - -/** - * The following classes exclude from lint - * - * - `android.**` - * - `androidx.**` - * - `com.android.**` - * - `com.google.android.**` - * - `com.google.gson.**` - * - `com.didiglobal.booster.instrument.**` - * - `**.R` - * - `**.R$*` - * - `BuildConfig` - */ -internal val EXCLUDES = Regex("^(((android[x]?)|(com/(((google/)?android)|(google/gson)|(didiglobal/booster/instrument))))/.+)|(.+/((R[2]?(${DOLLAR}[a-z]+)?)|(BuildConfig)))$") - - -internal val PLATFORM_METHODS_RUN_ON_UI_THREAD = arrayOf( - "androidx/asynclayoutinflater/view/AsyncLayoutInflater.inflate(ILandroid/view/ViewGroup;Landroidx/asynclayoutinflater/view/AsyncLayoutInflater${DOLLAR}OnInflateFinishedListener;)V" -).map(CallNode.Companion::valueOf).toSet() - -internal val PLATFORM_METHODS_RUN_ON_MAIN_THREAD = arrayOf( - "android/content/ContextWrapper.attachBaseContext(Landroid/content/Context;)V", - - "android/os/AsyncTask.onPreExecute()V", - "android/os/AsyncTask.onPostExecute(Ljava/lang/Object;)V", - "android/os/AsyncTask.onProgressUpdate([Ljava/lang/Object;)V", - "android/os/AsyncTask.onCancelled([Ljava/lang/Object;)V", - "android/os/AsyncTask.onCancelled()V", - "android/os/AsyncTask.execute([Ljava/lang/Object;)Landroid/os/AsyncTask;", - - "android/view/inputmethod/InputMethod.attachToken(Landroid/os/IBinder;)V", - "android/view/inputmethod/InputMethod.bindInput(Landroid/view/inputmethod/InputBinding;)V", - "android/view/inputmethod/InputMethod.unbindInput()V", - "android/view/inputmethod/InputMethod.startInput(Landroid/view/inputmethod/InputConnection;Landroid/view/inputmethod/EditorInfo;)V", - "android/view/inputmethod/InputMethod.restartInput(Landroid/view/inputmethod/InputConnection;Landroid/view/inputmethod/EditorInfo;)V", - "android/view/inputmethod/InputMethod.dispatchStartInputWithToken(Landroid/view/inputmethod/InputConnection;Landroid/view/inputmethod/EditorInfo;ZLandroid/os/IBinder;)V", - "android/view/inputmethod/InputMethod.createSession(Landroid/view/inputmethod/SessionCallback;)V", - "android/view/inputmethod/InputMethod.setSessionEnabled(Landroid/view/inputmethod/InputMethodSession;Z)V", - "android/view/inputmethod/InputMethod.revokeSession(Landroid/view/inputmethod/InputMethodSession;)V", - "android/view/inputmethod/InputMethod.showSoftInput(ILandroid/os/ResultReceiver;)V", - "android/view/inputmethod/InputMethod.hideSoftInput(ILandroid/os/ResultReceiver;)V", - "android/view/inputmethod/InputMethod.changeInputMethodSubtype(Landroid/view/inputmethod/InputMethodSubtype;)V", - - "androidx/fragment/app/Fragment.getViewLifecycleOwner()Landroidx/lifecycle/LifecycleOwner;", - - "androidx/lifecycle/Lifecycle.addObserver(Landroidx/lifecycle/Lifecycle/LifecycleObserver;)V", - "androidx/lifecycle/Lifecycle.removeObserver(Landroidx/lifecycle/Lifecycle/LifecycleObserver;)V", - "androidx/lifecycle/Lifecycle.getCurrentState()Landroidx/lifecycle/Lifecycle${DOLLAR}State;", - "androidx/lifecycle/LifecycleRegistry.markState(Landroidx/lifecycle/Lifecycle${DOLLAR}State;)V" -).map(CallNode.Companion::valueOf).toSet() - -internal val MAIN_THREAD_ANNOTATIONS = arrayOf( - "androidx/annotation/MainThread", - "android/support/annotation/MainThread", - "android/annotation/MainThread" -) - -internal val UI_THREAD_ANNOTATIONS = arrayOf( - "androidx/annotation/UiThread", - "android/support/annotation/UiThread", - "android/annotation/UiThread" -) - -internal val WORKER_THREAD_ANNOTATIONS = arrayOf( - "androidx/annotation/WorkerThread", - "android/support/annotation/WorkerThread", - "android/annotation/WorkerThread" -) - -internal val BINDER_THREAD_ANNOTATIONS = arrayOf( - "androidx/annotation/BinderThread", - "android/support/annotation/BinderThread", - "android/annotation/BinderThread" -) - -internal val ANY_THREAD_ANNOTATIONS = arrayOf( - "androidx/annotation/AnyThread", - "android/support/annotation/AnyThread", - "android/annotation/AnyThread" -) diff --git a/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/reference/ReferenceAnalysisTask.kt b/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/reference/ReferenceAnalysisTask.kt deleted file mode 100644 index 18f6da4ac..000000000 --- a/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/reference/ReferenceAnalysisTask.kt +++ /dev/null @@ -1,83 +0,0 @@ -package com.didiglobal.booster.task.analyser.reference - -import com.didiglobal.booster.cha.asm.Reference -import com.didiglobal.booster.cha.asm.ReferenceAnalyser -import com.didiglobal.booster.cha.fold -import com.didiglobal.booster.gradle.getJars -import com.didiglobal.booster.gradle.getResolvedArtifactResults -import com.didiglobal.booster.graph.Graph -import com.didiglobal.booster.graph.dot.DotGraph -import com.didiglobal.booster.graph.json.JsonGraphRender -import com.didiglobal.booster.kotlinx.green -import com.didiglobal.booster.kotlinx.yellow -import com.didiglobal.booster.task.analyser.AnalysisTask -import com.didiglobal.booster.task.analyser.report -import org.gradle.api.artifacts.component.ProjectComponentIdentifier -import org.gradle.api.tasks.TaskAction -import org.gradle.reporting.HtmlReportRenderer -import java.util.concurrent.Executors -import java.util.concurrent.TimeUnit - -/** - * Analysing the class reference for current variant to determine each class in this module is referenced by which class in which module - * - * @author johnsonlee - */ -open class ReferenceAnalysisTask : AnalysisTask() { - - override fun getDescription(): String = "Analysing class reference for Android/Java projects" - - @TaskAction - override fun analyse() { - val upstream = project.getResolvedArtifactResults(true, variant).associate { - it.id.componentIdentifier.displayName to when (val id = it.id.componentIdentifier) { - is ProjectComponentIdentifier -> project.rootProject.project(id.projectPath).getJars(variant).map { file -> - classSetCache[file.toURI().toURL()] - }.fold() - else -> classSetCache[it.file.toURI().toURL()] - } - } - - val origin = project.name to project.getJars(variant).map { - classSetCache[it.toURI().toURL()] - }.fold() - val graph = ReferenceAnalyser().analyse(origin, upstream) { klass, progress, duration -> - project.logger.info("${green(String.format("%3f%%", progress * 100))} Analyse class ${klass.name} in ${yellow(duration.toMillis())} ms") - } - val executor = Executors.newFixedThreadPool(3) - - try { - arrayOf(::generateHtmlReport, ::generateDotReport, ::generateJsonReport).map { render -> - executor.submit { - render(graph) - } - }.forEach { - it.get() - } - } finally { - executor.shutdown() - executor.awaitTermination(1, TimeUnit.MINUTES) - } - } - - private fun generateDotReport(graph: Graph) { - try { - val options = DotGraph.DotOptions(rankdir = "LR", format = "svg") - DotGraph.DIGRAPH.visualize(graph, report("dot"), options) - } catch (e: Exception) { - logger.error(e.message) - } - } - - private fun generateHtmlReport(graph: Graph) { - HtmlReportRenderer().renderSinglePage(graph, ReferencePageRenderer(project, variant), report("html")) - } - - private fun generateJsonReport(graph: Graph) { - val json = JsonGraphRender.render(graph) { node -> - """{"component": "${node.component}", "class": "${node.klass}"}""" - }.toString() - report("json").writeText(json) - } - -} diff --git a/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/reference/ReferencePageRenderer.kt b/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/reference/ReferencePageRenderer.kt deleted file mode 100644 index 43b36c336..000000000 --- a/booster-task-analyser/src/main/kotlin/com/didiglobal/booster/task/analyser/reference/ReferencePageRenderer.kt +++ /dev/null @@ -1,58 +0,0 @@ -package com.didiglobal.booster.task.analyser.reference - -import com.android.build.gradle.api.BaseVariant -import com.didiglobal.booster.cha.asm.Reference -import com.didiglobal.booster.graph.Graph -import org.gradle.api.Project -import org.gradle.internal.html.SimpleHtmlWriter -import org.gradle.reporting.ReportRenderer -import org.gradle.reporting.TabbedPageRenderer -import java.net.URL - -class ReferencePageRenderer( - private val project: Project, - private val variant: BaseVariant? -) : TabbedPageRenderer>() { - - private val _title: String by lazy { - if (variant == null) project.name else "${project.name}:${variant.name}" - } - - override fun getTitle(): String = _title - - override fun getHeaderRenderer(): ReportRenderer, SimpleHtmlWriter> = object : ReportRenderer, SimpleHtmlWriter>() { - override fun render(model: Graph, output: SimpleHtmlWriter) { - output.startElement("p").attribute("class", "subtitle").characters(project.description ?: "").endElement() - } - } - - override fun getContentRenderer(): ReportRenderer, SimpleHtmlWriter> = object : ReportRenderer, SimpleHtmlWriter>() { - override fun render(model: Graph, output: SimpleHtmlWriter) { - output.run { - model.groupBy { - it.to.groupBy() - }.toSortedMap(Reference.COMPONENT_COMPARATOR).map { (group, edges) -> - group to edges.groupBy({ it.to.klass }) { it.from.klass } - }.forEach { (title, references) -> - startElement("h2").characters(title).endElement() - startElement("ul").attribute("class", "refs") - references.forEach { (ref, sources) -> - startElement("li") - startElement("div").characters(ref).endElement() - startElement("ul") - sources.forEach { - startElement("li").characters(it).endElement() - } - endElement() - endElement() - } - endElement() - } - } - } - - } - - override fun getStyleUrl(): URL = ReferencePageRenderer::class.java.getResource("/style.css") - -} diff --git a/booster-task-analyser/src/main/resources/blacklist.txt b/booster-task-analyser/src/main/resources/blacklist.txt deleted file mode 100644 index fbf3bca3f..000000000 --- a/booster-task-analyser/src/main/resources/blacklist.txt +++ /dev/null @@ -1,166 +0,0 @@ -java/lang/Object.wait()V -java/lang/Object.wait(J)V -java/lang/Object.wait(JI)V -java/lang/Thread.start()V -java/lang/Thread.sleep(J)V -java/lang/Thread.sleep(JI)V -java/lang/ClassLoader.getResource(Ljava/lang/String;)Ljava/net/URL; -java/lang/ClassLoader.getResources(Ljava/lang/String;)Ljava/util/Enumeration; -java/lang/ClassLoader.getResourceAsStream(Ljava/lang/String;)Ljava/io/InputStream; -java/lang/ClassLoader.getSystemResource(Ljava/lang/String;)Ljava/net/URL; -java/lang/ClassLoader.getSystemResources(Ljava/lang/String;)Ljava/util/Enumeration; -java/lang/ClassLoader.getSystemResourceAsStream(Ljava/lang/String;)Ljava/io/InputStream; -java/io/FileDescriptor.sync()V -java/io/FileInputStream.(Ljava/io/File;)V -java/io/FileInputStream.(Ljava/io/FileDescriptor;)V -java/io/FileInputStream.(Ljava/lang/String;)V -java/io/FileInputStream.available()I -java/io/FileInputStream.close()I -java/io/FileInputStream.getChannel()Ljava/nio/channels/FileChannel; -java/io/FileInputStream.getFD()Ljava/io/FileDescriptor; -java/io/FileInputStream.read()I -java/io/FileInputStream.read([B)I -java/io/FileInputStream.read([BII)I -java/io/FileInputStream.reset()V -java/io/FileInputStream.skip(J)J -java/io/FileOutputStream.(Ljava/io/File;)V -java/io/FileOutputStream.(Ljava/io/File;Z)V -java/io/FileOutputStream.(Ljava/io/FileDescriptor;)V -java/io/FileOutputStream.(Ljava/lang/String;)V -java/io/FileOutputStream.(Ljava/lang/String;Z)V -java/io/FileOutputStream.flush()V -java/io/FileOutputStream.getChannel()Ljava/nio/channels/FileChannel; -java/io/FileOutputStream.getFD()Ljava/io/FileDescriptor; -java/io/FileOutputStream.write(I)V -java/io/FileOutputStream.write([B)V -java/io/FileOutputStream.write([BII)V -java/io/FileReader.(Ljava/io/File;)V -java/io/FileReader.(Ljava/io/FileDescriptor;)V -java/io/FileReader.(Ljava/lang/String;)V -java/io/FileReader.read()I -java/io/FileReader.read([C)I -java/io/FileReader.read([CII)I -java/io/FileReader.read(Ljava/nio/CharBuffer;)I -java/io/FileReader.ready()Z -java/io/FileReader.reset()V -java/io/FileReader.skip(J)J -java/io/FileWriter.(Ljava/io/File;)V -java/io/FileWriter.(Ljava/io/File;Z)V -java/io/FileWriter.(Ljava/io/FileDescriptor;)V -java/io/FileWriter.(Ljava/lang/String;)V -java/io/FileWriter.(Ljava/lang/String;Z)V -java/io/FileWriter.append(C)Ljava/io/Writer; -java/io/FileWriter.append(Ljava/lang/CharSequence;)Ljava/io/Writer; -java/io/FileWriter.append(Ljava/lang/CharSequence;II)Ljava/io/Writer; -java/io/FileWriter.flush()V -java/io/FileWriter.write(I)V -java/io/FileWriter.write(Ljava/lang/String;)V -java/io/FileWriter.write(Ljava/lang/String;II)V -java/io/FileWriter.write([C)V -java/io/FileWriter.write([CII)V -java/io/RandomAccessFile.(Ljava/io/File;Ljava/lang/String;)V -java/io/RandomAccessFile.(Ljava/lang/String;Ljava/lang/String;)V -java/io/RandomAccessFile.close()V -java/io/RandomAccessFile.getChannel()Ljava/nio/channels/FileChannel; -java/io/RandomAccessFile.getFilePointer()J -java/io/RandomAccessFile.read()I -java/io/RandomAccessFile.read([B)I -java/io/RandomAccessFile.read([BII)I -java/io/RandomAccessFile.readBoolean()Z -java/io/RandomAccessFile.readByte()B -java/io/RandomAccessFile.readChar()C -java/io/RandomAccessFile.readDouble()D -java/io/RandomAccessFile.readFloat()F -java/io/RandomAccessFile.readFully([B)V -java/io/RandomAccessFile.readFully([BII)V -java/io/RandomAccessFile.readInt()I -java/io/RandomAccessFile.readLine()Ljava/lang/String; -java/io/RandomAccessFile.readLong()J -java/io/RandomAccessFile.readShort()S -java/io/RandomAccessFile.readUnsignedByte()I -java/io/RandomAccessFile.readUnsignedShort()I -java/io/RandomAccessFile.readUTF()Ljava/lang/String; -java/io/RandomAccessFile.seek(J)V -java/io/RandomAccessFile.skipBytes(I)I -java/io/RandomAccessFile.write([B)V -java/io/RandomAccessFile.write([BII)V -java/io/RandomAccessFile.write(I)V -java/io/RandomAccessFile.writeBoolean(Z)V -java/io/RandomAccessFile.writeByte(I)V -java/io/RandomAccessFile.writeBytes(Ljava/lang/String;)V -java/io/RandomAccessFile.writeChar(I)V -java/io/RandomAccessFile.writeChars(Ljava/lang/String;)V -java/io/RandomAccessFile.writeDouble(D)V -java/io/RandomAccessFile.writeFloat(F)V -java/io/RandomAccessFile.writeInt(I)V -java/io/RandomAccessFile.writeLong(J)V -java/io/RandomAccessFile.writeShort(I)V -java/io/RandomAccessFile.writeUTF(Ljava/lang/String;)V -java/net/URL.openConnection()Ljava/net/URLConnection; -java/net/URL.openConnection(Ljava/net/Proxy;)Ljava/net/URLConnection; -java/net/URL.openStream()Ljava/io/InputStream; -java/nio/channels/FileChannel.lock()Ljava/nio/channels/FileLock; -java/nio/channels/FileChannel.lock(JJZ)Ljava/nio/channels/FileLock; -java/util/concurrent/locks/Lock.lock()V -java/util/concurrent/locks/Condition.await()V -java/util/concurrent/locks/Condition.awaitUninterruptibly()V -java/util/concurrent/locks/Condition.awaitNanos(J)J -java/util/concurrent/locks/Condition.await(JLjava/util/concurrent/TimeUnit;)Z -java/util/concurrent/locks/Condition.awaitUntil(Ljava/util/Date;)Z -java/util/ServiceLoader.load(Ljava/lang/Class;)Ljava/util/ServiceLoader; -java/util/ServiceLoader.load(Ljava/lang/Class;Ljava/lang/ClassLoader;)Ljava/util/ServiceLoader; -java/util/zip/ZipFile.(Ljava/lang/String;) -java/util/zip/ZipFile.getInputStream(Ljava/util/zip/ZipEntry;) -java/util/jar/JarFile.(Ljava/lang/String;) -java/util/jar/JarFile.getInputStream(Ljava/util/jar/JarEntry;) -android/content/Context.getSharedPreferences(Ljava/lang/String;I)Landroid/content/SharedPreferences; -android/content/ContentResolver.openInputStream(Landroid/net/Uri;)Ljava/io/InputStream; -android/content/ContentResolver.openOutputStream(Landroid/net/Uri;Ljava/lang/String;)Ljava/io/OutputStream; -android/content/res/AssetFileDescriptor.createInputStream()Ljava/io/FileInputStream; -android/content/res/AssetFileDescriptor.createOutputStream()Ljava/io/FileOutputStream; -android/content/SharedPreferences$Editor.apply()V -android/content/SharedPreferences$Editor.commit()B -android/content/res/AssetManager.list(Ljava/lang/String;)[Ljava/lang/String; -android/content/res/AssetManager.open(Ljava/lang/String;)Ljava/io/InputStream; -android/content/res/AssetManager.open(Ljava/lang/String;I)Ljava/io/InputStream; -android/content/res/AssetManager.openFd(Ljava/lang/String;)Landroid/content/res/AssetFileDescriptor; -android/content/res/AssetManager.openNonAssetFd(Ljava/lang/String;)Landroid/content/res/AssetFileDescriptor; -android/content/res/AssetManager.openNonAssetFd(ILjava/lang/String;)Landroid/content/res/AssetFileDescriptor; -android/content/res/AssetManager.openXmlResourceParser(Ljava/lang/String;)Landroid/content/res/XmlResourceParser; -android/content/res/AssetManager.openXmlResourceParser(ILjava/lang/String;)Landroid/content/res/XmlResourceParser; -android/database/sqlite/SQLiteDatabase.beginTransaction()V -android/database/sqlite/SQLiteDatabase.beginTransactionNonExclusive()V -android/database/sqlite/SQLiteDatabase.beginTransactionWithListener(Landroid/database/sqlite/SQLiteTransactionListener;)V -android/database/sqlite/SQLiteDatabase.delete(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V -android/database/sqlite/SQLiteDatabase.deleteDatabase(Ljava/io/File;)Z -android/database/sqlite/SQLiteDatabase.endTransaction()V -android/database/sqlite/SQLiteDatabase.execSQL(Ljava/lang/String;)V -android/database/sqlite/SQLiteDatabase.execSQL(Ljava/lang/String;[Ljava/lang/Object;)V -android/database/sqlite/SQLiteDatabase.insert(Ljava/lang/String;Ljava/lang/String;Landroid/content/ContentValues;)J -android/database/sqlite/SQLiteDatabase.insertOrThrow(Ljava/lang/String;Ljava/lang/String;Landroid/content/ContentValues;)J -android/database/sqlite/SQLiteDatabase.insertWithOnConflict(Ljava/lang/String;Ljava/lang/String;Landroid/content/ContentValues;I)J -android/database/sqlite/SQLiteDatabase.query(ZLjava/lang/String;[java/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor; -android/database/sqlite/SQLiteDatabase.query(Ljava/lang/String;[java/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor; -android/database/sqlite/SQLiteDatabase.query(ZLjava/lang/String;[java/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/os/CancellationSignal;)Landroid/database/Cursor; -android/database/sqlite/SQLiteDatabase.query(Ljava/lang/String;[java/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor; -android/database/sqlite/SQLiteDatabase.queryWithFactory(Landroid/database/sqlite/SQLiteDatabase$CursorFactory;ZLjava/lang/String;[java/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/os/CancellationSignal;)Landroid/database/Cursor; -android/database/sqlite/SQLiteDatabase.queryWithFactory(Landroid/database/sqlite/SQLiteDatabase$CursorFactory;ZLjava/lang/String;[java/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor; -android/database/sqlite/SQLiteDatabase.rawQuery(Ljava/lang/String;[Ljava/lang/String;Landroid/os/CancellationSignal;)Landroid/database/Cursor; -android/database/sqlite/SQLiteDatabase.rawQuery(Ljava/lang/String;[Ljava/lang/String;)Landroid/database/Cursor; -android/database/sqlite/SQLiteDatabase.rawQueryWithFactory(Landroid/database/sqlite/SQLiteDatabase$CursorFactory;Ljava/lang/String;[java/lang/String;Ljava/lang/String;Landroid/os/CancellationSignal;)Landroid/database/Cursor; -android/database/sqlite/SQLiteDatabase.rawQueryWithFactory(Landroid/database/sqlite/SQLiteDatabase$CursorFactory;Ljava/lang/String;[java/lang/String;Ljava/lang/String;)Landroid/database/Cursor; -android/database/sqlite/SQLiteDatabase.replace(Ljava/lang/String;Ljava/lang/String;Landroid/content/ContentValues;)J -android/database/sqlite/SQLiteDatabase.replaceOrThrow(Ljava/lang/String;Ljava/lang/String;Landroid/content/ContentValues;)J -android/database/sqlite/SQLiteDatabase.update(Ljava/lang/String;Ljava/lang/String;Landroid/content/ContentValues;)J -android/database/sqlite/SQLiteDatabase.updateWithOnConflict(Ljava/lang/String;Landroid/content/ContentValues;Ljava/lang/String;[Ljava/lang/String;I)J -android/graphics/BitmapFactory.decodeByteArray([BIILandroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap; -android/graphics/BitmapFactory.decodeByteArray([BII)Landroid/graphics/Bitmap; -android/graphics/BitmapFactory.decodeFile(Ljava/lang/String;Landroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap; -android/graphics/BitmapFactory.decodeFile(Ljava/lang/String;)Landroid/graphics/Bitmap; -android/graphics/BitmapFactory.decodeFileDescriptor(Ljava/io/FileDescriptor;)Landroid/graphics/Bitmap; -android/graphics/BitmapFactory.decodeFileDescriptor(Ljava/io/FileDescriptor;Landroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap; -android/graphics/BitmapFactory.decodeResource(Landroid/content/res/Resources;I)Landroid/graphics/Bitmap; -android/graphics/BitmapFactory.decodeResource(Landroid/content/res/Resources;ILandroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap; -android/graphics/BitmapFactory.decodeResourceStream(Landroid/content/res/Resources;Landroid/util/TypedValue;Ljava/io/InputStream;Landroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap; -android/graphics/BitmapFactory.decodeStream(Ljava/io/InputStream;)Landroid/graphics/Bitmap; -android/graphics/BitmapFactory.decodeStream(Ljava/io/InputStream;Landroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap; diff --git a/booster-task-analyser/src/main/resources/style.css b/booster-task-analyser/src/main/resources/style.css deleted file mode 100644 index 0623a9e0a..000000000 --- a/booster-task-analyser/src/main/resources/style.css +++ /dev/null @@ -1,7 +0,0 @@ -html { - font-family: arial, sans-serif; -} - -ul.refs ul { - color: rgba(0, 0, 0, 0.3); -} diff --git a/booster-task-analyser/src/main/resources/whitelist.txt b/booster-task-analyser/src/main/resources/whitelist.txt deleted file mode 100644 index 0b1912436..000000000 --- a/booster-task-analyser/src/main/resources/whitelist.txt +++ /dev/null @@ -1,2 +0,0 @@ -timber/log/Timber$Tree.getStackTraceString(Ljava/lang/Throwable;)Ljava/lang/String; -com/umeng/commonsdk/statistics/common/ULog.getStackTraceString(Ljava/lang/Throwable;)Ljava/lang/String; diff --git a/booster-task-analyser/src/test/java/androidx/annotation/MainThread.java b/booster-task-analyser/src/test/java/androidx/annotation/MainThread.java deleted file mode 100644 index ca5c5fad9..000000000 --- a/booster-task-analyser/src/test/java/androidx/annotation/MainThread.java +++ /dev/null @@ -1,11 +0,0 @@ -package androidx.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.TYPE, ElementType.PARAMETER}) -public @interface MainThread { -} diff --git a/booster-task-analyser/src/test/java/org/greenrobot/eventbus/Subscribe.java b/booster-task-analyser/src/test/java/org/greenrobot/eventbus/Subscribe.java deleted file mode 100644 index b805163a4..000000000 --- a/booster-task-analyser/src/test/java/org/greenrobot/eventbus/Subscribe.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.greenrobot.eventbus; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -public @interface Subscribe { - - ThreadMode threadMode() default ThreadMode.POSTING; - -} diff --git a/booster-task-analyser/src/test/java/org/greenrobot/eventbus/ThreadMode.java b/booster-task-analyser/src/test/java/org/greenrobot/eventbus/ThreadMode.java deleted file mode 100644 index 75cd02481..000000000 --- a/booster-task-analyser/src/test/java/org/greenrobot/eventbus/ThreadMode.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.greenrobot.eventbus; - -public enum ThreadMode { - - POSTING, - MAIN, - BACKGROUND, - ASYNC -} diff --git a/booster-task-analyser/src/test/kotlin/com/didiglobal/booster/task/analyser/AnalyserTaskTest.kt b/booster-task-analyser/src/test/kotlin/com/didiglobal/booster/task/analyser/AnalyserTaskTest.kt deleted file mode 100644 index b77b92d59..000000000 --- a/booster-task-analyser/src/test/kotlin/com/didiglobal/booster/task/analyser/AnalyserTaskTest.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.didiglobal.booster.task.analyser - -import com.didiglobal.booster.kotlinx.Wildcard -import com.didiglobal.booster.task.analyser.performance.VALUE_BLACKLIST -import java.net.URL -import kotlin.test.Test -import kotlin.test.assertNotNull -import kotlin.test.assertTrue - -class AnalyserTaskTest { - - @Test - fun `check if blacklist exists`() { - assertNotNull(VALUE_BLACKLIST) - assertTrue(URL(VALUE_BLACKLIST).openStream().bufferedReader().use { - it.readLines().map(Wildcard.Companion::valueOf).toSet() - }.isNotEmpty()) - } - -} \ No newline at end of file diff --git a/booster-task-analyser/src/test/kotlin/com/didiglobal/booster/task/analyser/AnnotationExample1.kt b/booster-task-analyser/src/test/kotlin/com/didiglobal/booster/task/analyser/AnnotationExample1.kt deleted file mode 100644 index be9951f89..000000000 --- a/booster-task-analyser/src/test/kotlin/com/didiglobal/booster/task/analyser/AnnotationExample1.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.didiglobal.booster.task.analyser - -import androidx.annotation.MainThread - -@MainThread -class AnnotationExample1 { - - fun fun1() { - } - - fun fun2() { - } - - fun fun3() { - } - - fun fun4() { - } - -} \ No newline at end of file diff --git a/booster-task-analyser/src/test/kotlin/com/didiglobal/booster/task/analyser/AnnotationExample2.kt b/booster-task-analyser/src/test/kotlin/com/didiglobal/booster/task/analyser/AnnotationExample2.kt deleted file mode 100644 index 5e0e05c58..000000000 --- a/booster-task-analyser/src/test/kotlin/com/didiglobal/booster/task/analyser/AnnotationExample2.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.didiglobal.booster.task.analyser - -import org.greenrobot.eventbus.Subscribe -import org.greenrobot.eventbus.ThreadMode - -class AnnotationExample2 { - - @Subscribe(threadMode = ThreadMode.MAIN) - fun fun1() { - } - - @Subscribe(threadMode = ThreadMode.MAIN) - fun fun2() { - } - - @Subscribe(threadMode = ThreadMode.MAIN) - fun fun3() { - } - - @Subscribe(threadMode = ThreadMode.MAIN) - fun fun4() { - } - -} \ No newline at end of file diff --git a/booster-task-analyser/src/test/kotlin/com/didiglobal/booster/task/analyser/URITest.kt b/booster-task-analyser/src/test/kotlin/com/didiglobal/booster/task/analyser/URITest.kt deleted file mode 100644 index c8828b887..000000000 --- a/booster-task-analyser/src/test/kotlin/com/didiglobal/booster/task/analyser/URITest.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.didiglobal.booster.task.analyser - -import java.net.URI -import kotlin.test.Test -import kotlin.test.assertFalse -import kotlin.test.assertTrue - -class URITest { - - @Test - fun `parse string as uri`() { - val home = URI(System.getProperty("user.home")) - assertFalse(home.isAbsolute) - val github = URI("http://github.com") - assertTrue(github.isAbsolute) - } - -} diff --git a/booster-task-analyser/src/test/resources/AnnotationExample1.class b/booster-task-analyser/src/test/resources/AnnotationExample1.class deleted file mode 100644 index b19681543..000000000 Binary files a/booster-task-analyser/src/test/resources/AnnotationExample1.class and /dev/null differ diff --git a/booster-task-analyser/src/test/resources/AnnotationExample2.class b/booster-task-analyser/src/test/resources/AnnotationExample2.class deleted file mode 100644 index e301e5d8e..000000000 Binary files a/booster-task-analyser/src/test/resources/AnnotationExample2.class and /dev/null differ diff --git a/booster-task-check-snapshot/README.md b/booster-task-check-snapshot/README.md deleted file mode 100644 index ee4d2e841..000000000 --- a/booster-task-check-snapshot/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# booster-task-check-snapshot - -This module is used for snapshot dependencies checking - -本模块用于检查依赖中是否包含有 snapshot 的依赖项 - -## Getting Started - -```bash -./gradlew checkSnapshot -``` - diff --git a/booster-task-check-snapshot/build.gradle b/booster-task-check-snapshot/build.gradle deleted file mode 100644 index 0afb3ba9b..000000000 --- a/booster-task-check-snapshot/build.gradle +++ /dev/null @@ -1,9 +0,0 @@ -apply from: "$rootDir/gradle/booster.gradle" - -dependencies { - kapt "com.google.auto.service:auto-service:1.0" - implementation 'com.google.auto.service:auto-service:1.0' - implementation project(':booster-api') - compileOnly 'com.android.tools.build:gradle:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' -} diff --git a/booster-task-check-snapshot/src/main/kotlin/com/didiglobal/booster/task/dependency/CheckSnapshot.kt b/booster-task-check-snapshot/src/main/kotlin/com/didiglobal/booster/task/dependency/CheckSnapshot.kt deleted file mode 100644 index c76cdbd2a..000000000 --- a/booster-task-check-snapshot/src/main/kotlin/com/didiglobal/booster/task/dependency/CheckSnapshot.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.didiglobal.booster.task.dependency - -import com.android.build.gradle.api.BaseVariant -import com.didiglobal.booster.gradle.dependencies -import com.didiglobal.booster.kotlinx.CSI_RESET -import com.didiglobal.booster.kotlinx.CSI_YELLOW -import com.didiglobal.booster.kotlinx.ifNotEmpty -import org.gradle.api.DefaultTask -import org.gradle.api.internal.artifacts.repositories.resolver.MavenUniqueSnapshotComponentIdentifier -import org.gradle.api.tasks.Internal -import org.gradle.api.tasks.TaskAction - -internal open class CheckSnapshot : DefaultTask() { - - @get:Internal - lateinit var variant: BaseVariant - - @TaskAction - fun run() { - if (!variant.buildType.isDebuggable) { - variant.dependencies.filter { - it.id.componentIdentifier is MavenUniqueSnapshotComponentIdentifier - }.map { - it.id.componentIdentifier as MavenUniqueSnapshotComponentIdentifier - }.ifNotEmpty { snapshots -> - println("$CSI_YELLOW ⚠️ ${snapshots.size} SNAPSHOT artifacts found in ${variant.name} variant:$CSI_RESET\n${snapshots.joinToString("\n") { snapshot -> "$CSI_YELLOW→ ${snapshot.displayName}$CSI_RESET" }}") - } - } - } - -} diff --git a/booster-task-check-snapshot/src/main/kotlin/com/didiglobal/booster/task/dependency/CheckSnapshotVariantProcessor.kt b/booster-task-check-snapshot/src/main/kotlin/com/didiglobal/booster/task/dependency/CheckSnapshotVariantProcessor.kt deleted file mode 100644 index 6e4e33e1d..000000000 --- a/booster-task-check-snapshot/src/main/kotlin/com/didiglobal/booster/task/dependency/CheckSnapshotVariantProcessor.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.didiglobal.booster.task.dependency - -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.internal.tasks.factory.dependsOn -import com.didiglobal.booster.BOOSTER -import com.didiglobal.booster.gradle.javaCompilerTaskProvider -import com.didiglobal.booster.gradle.project -import com.didiglobal.booster.task.spi.VariantProcessor -import com.google.auto.service.AutoService -import org.gradle.api.UnknownTaskException - -private const val TASK_NAME = "checkSnapshot" - -@AutoService(VariantProcessor::class) -class CheckSnapshotVariantProcessor : VariantProcessor { - - override fun process(variant: BaseVariant) { - variant.project.tasks.let { tasks -> - val checkSnapshot = try { - tasks.named(TASK_NAME) - } catch (e: UnknownTaskException) { - tasks.register(TASK_NAME) { - it.group = BOOSTER - it.description = "Check snapshot dependencies" - } - } - @Suppress("DEPRECATION") - tasks.register("check${variant.name.capitalize()}Snapshot", CheckSnapshot::class.java) { - it.group = BOOSTER - it.description = "Check snapshot dependencies for ${variant.name}" - it.variant = variant - it.outputs.upToDateWhen { false } - }.also { - variant.javaCompilerTaskProvider.dependsOn(it) - checkSnapshot.dependsOn(it) - } - } - } - -} diff --git a/booster-task-compression-cwebp/README.md b/booster-task-compression-cwebp/README.md deleted file mode 100644 index 1dc3f5051..000000000 --- a/booster-task-compression-cwebp/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# booster-task-compression-cwebp - -This module is used for assets and resource compression using `cwebp` - -## Properties - -The following table shows the properties that transformer supports: - -| Property | Description | Example | -| ---------------------------------------- | ---------------------------------------- | ------------------------------------------- | -| `booster.task.compression.cwebp.quality` | compression quality (the default is 80) | | -| `booster.task.compression.cwebp.ignores` | ignore wildcards (separated by comma) | `mipmap/ic_launcher*,drawable/ic_launcher*` | - -## Using `cwebp` - -```bash -./gradlew assembleDebug -Pbooster.task.compression.cwebp.quality=75 -``` - -or configured in the `gradle.properties`: - -```properties -booster.task.compression.cwebp.quality=75 -``` diff --git a/booster-task-compression-cwebp/build.gradle b/booster-task-compression-cwebp/build.gradle deleted file mode 100644 index 42eaccc1b..000000000 --- a/booster-task-compression-cwebp/build.gradle +++ /dev/null @@ -1,10 +0,0 @@ -apply from: "$rootDir/gradle/booster.gradle" - -dependencies { - kapt "com.google.auto.service:auto-service:1.0" - implementation project(':booster-task-compression') - compileOnly 'com.android.tools.build:gradle:4.0.0' - compileOnly 'com.android.tools.build:builder:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' - testCompileOnly 'com.android.tools.build:builder:4.0.0' -} diff --git a/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/AbstractCwebpCompressImages.kt b/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/AbstractCwebpCompressImages.kt deleted file mode 100644 index 69ea00885..000000000 --- a/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/AbstractCwebpCompressImages.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.didiglobal.booster.task.compression.cwebp - -import com.didiglobal.booster.compression.CompressionOptions -import com.didiglobal.booster.compression.task.CompressImages -import com.didiglobal.booster.gradle.getProperty -import org.gradle.api.tasks.TaskAction -import java.io.File - -/** - * Represents an abstraction of cwebp compression task - * - * @author johnsonlee - */ -abstract class AbstractCwebpCompressImages : CompressImages() { - - @TaskAction - fun run() { - this.options = CompressionOptions(project.getProperty(PROPERTY_OPTION_QUALITY, 80)) - compress(File::hasNotAlpha) - } - - protected abstract fun compress(filter: (File) -> Boolean) - -} \ No newline at end of file diff --git a/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/CWebpProvider.kt b/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/CWebpProvider.kt deleted file mode 100644 index cd7651ab0..000000000 --- a/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/CWebpProvider.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.didiglobal.booster.task.compression.cwebp - -import com.didiglobal.booster.command.Command -import com.didiglobal.booster.command.CommandProvider -import com.google.auto.service.AutoService - -/** - * Represents cwebp command provider - * - * @author johnsonlee - */ -@AutoService(CommandProvider::class) -class CWebpProvider : CommandProvider { - - override fun get(): Collection = listOf(Command(CWEBP, javaClass.classLoader.getResource(PREBUILT_CWEBP_EXECUTABLE)!!)) - -} \ No newline at end of file diff --git a/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/Cwebp.kt b/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/Cwebp.kt deleted file mode 100644 index f14eee40a..000000000 --- a/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/Cwebp.kt +++ /dev/null @@ -1,82 +0,0 @@ -package com.didiglobal.booster.task.compression.cwebp - -import com.android.build.gradle.api.BaseVariant -import com.didiglobal.booster.command.CommandService -import com.didiglobal.booster.compression.CompressionTool -import com.didiglobal.booster.compression.SimpleCompressionTaskCreator -import com.didiglobal.booster.gradle.minSdkVersion -import com.didiglobal.booster.kotlinx.OS -import com.didiglobal.booster.task.compression.cwebp.Cwebp.Companion.PROGRAM - -/** - * Represents utility class for webp compression - * - * @author johnsonlee - * - * @property opaque The value indicates if compression supports transparent images - */ -class Cwebp internal constructor(val supportAlpha: Boolean) : CompressionTool(CommandService.get(CWEBP)) { - - override fun newCompressionTaskCreator() = SimpleCompressionTaskCreator(this) { aapt2 -> - when (aapt2) { - true -> when (supportAlpha) { - true -> CwebpCompressOpaqueFlatImages::class - else -> CwebpCompressFlatImages::class - } - - else -> when (supportAlpha) { - true -> CwebpCompressOpaqueImages::class - else -> CwebpCompressImages::class - } - } - } - - companion object { - - const val PROGRAM = "cwebp" - - /** - * @see convert-webp - */ - fun get(variant: BaseVariant): Cwebp? { - val minSdkVersion = variant.minSdkVersion.apiLevel - return when { - minSdkVersion >= 18 -> Cwebp(true) - minSdkVersion in 14..17 -> Cwebp(false) - else -> null - } - } - - } - -} - -private val X64 = setOf("x64", "x86_64", "amd64") - -internal val CWEBP = "$PROGRAM${OS.executableSuffix}" - -internal val PREBUILT_CWEBP_EXECUTABLE = "bin/" + when { - OS.isLinux() -> { - "linux/" + if (OS.arch in X64) "x64" else TODO("Unsupported architecture ${OS.arch}") - } - OS.isMac() -> { - "macosx/" + when { - "arm64" == OS.arch || "arm64" in OS.uname -> "arm64" - OS.arch in X64 -> "x64/" + when { - OS.version >= "10.15" -> "10.15" - OS.version >= "10.14" -> "10.14" - OS.version >= "10.13" -> "10.13" - OS.version >= "10.12" -> "10.12" - else -> TODO("Unsupported system version ${OS.version}") - } - else -> TODO("Unsupported architecture ${OS.arch}") - } - } - OS.isWindows() -> { - "windows/" + if (OS.arch in X64) "x64" else TODO("Unsupported architecture ${OS.arch}") - } - else -> TODO("Unsupported OS ${OS.name}") -} + "/$CWEBP" - -private val PROPERTY_PREFIX = Build.ARTIFACT.replace('-', '.') -internal val PROPERTY_OPTION_QUALITY = "${PROPERTY_PREFIX}.option.quality" diff --git a/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/CwebpCompressFlatImages.kt b/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/CwebpCompressFlatImages.kt deleted file mode 100644 index cd57b33ad..000000000 --- a/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/CwebpCompressFlatImages.kt +++ /dev/null @@ -1,106 +0,0 @@ -package com.didiglobal.booster.task.compression.cwebp - -import com.android.SdkConstants -import com.android.SdkConstants.FD_RES -import com.android.builder.model.AndroidProject.FD_INTERMEDIATES -import com.android.sdklib.BuildToolInfo -import com.didiglobal.booster.aapt2.Aapt2Container -import com.didiglobal.booster.aapt2.metadata -import com.didiglobal.booster.compression.CompressionResult -import com.didiglobal.booster.compression.task.Aapt2ActionData -import com.didiglobal.booster.gradle.buildTools -import com.didiglobal.booster.gradle.mergedManifests -import com.didiglobal.booster.gradle.project -import com.didiglobal.booster.kotlinx.CSI_RED -import com.didiglobal.booster.kotlinx.CSI_RESET -import com.didiglobal.booster.kotlinx.file -import com.didiglobal.booster.kotlinx.search -import org.gradle.api.tasks.CacheableTask -import org.gradle.api.tasks.OutputDirectory -import java.io.File -import java.util.stream.Collectors -import javax.xml.parsers.SAXParserFactory - -/** - * Represents a task for compiled image compression using cwebp - * - * @author johnsonlee - */ -@CacheableTask -internal abstract class CwebpCompressFlatImages : AbstractCwebpCompressImages() { - - @get:OutputDirectory - val compressedRes: File - get() = variant.project.buildDir.file(FD_INTERMEDIATES).file("compressed_${FD_RES}_cwebp", variant.dirName, this.name) - - override fun compress(filter: (File) -> Boolean) { - val cwebp = this.compressor.canonicalPath - val aapt2 = variant.buildTools.getPath(BuildToolInfo.PathId.AAPT2) - val parser = SAXParserFactory.newInstance().newSAXParser() - val icons = variant.mergedManifests.search { - it.name == SdkConstants.ANDROID_MANIFEST_XML - }.parallelStream().map { manifest -> - LauncherIconHandler().let { - parser.parse(manifest, it) - it.icons - } - }.flatMap { - it.parallelStream() - }.collect(Collectors.toSet()) - - // Google Play only accept APK with PNG format launcher icon - // https://developer.android.com/topic/performance/reduce-apk-size#use-webp - val isNotLauncherIcon: (Pair) -> Boolean = { (input, metadata) -> - if (!icons.contains(metadata.resourceName)) true else false.also { - ignore(metadata.resourceName, input, File(metadata.sourcePath)) - } - } - - images().parallelStream().map { - it to it.metadata - }.filter(this::includes).filter(isNotLauncherIcon).filter { - filter(File(it.second.sourcePath)) - }.map { - val output = compressedRes.file("${it.second.resourcePath.substringBeforeLast('.')}.webp") - Aapt2ActionData(it.first, it.second, output, - listOf(cwebp, "-mt", "-quiet", "-q", options.quality.toString(), it.second.sourcePath, "-o", output.canonicalPath), - listOf(aapt2, "compile", "-o", it.first.parent, output.canonicalPath)) - }.forEach { - it.output.parentFile.mkdirs() - val s0 = File(it.metadata.sourcePath).length() - val rc = project.exec { spec -> - spec.isIgnoreExitValue = true - spec.commandLine = it.cmdline - } - when (rc.exitValue) { - 0 -> { - val s1 = it.output.length() - if (s1 > s0) { - results.add(CompressionResult(it.input, s0, s0, File(it.metadata.sourcePath))) - it.output.delete() - } else { - val rcAapt2 = project.exec { spec -> - spec.isIgnoreExitValue = true - spec.commandLine = it.aapt2 - } - if (0 == rcAapt2.exitValue) { - results.add(CompressionResult(it.input, s0, s1, File(it.metadata.sourcePath))) - it.input.delete() - } else { - logger.error("${CSI_RED}Command `${it.aapt2.joinToString(" ")}` exited with non-zero value ${rc.exitValue}$CSI_RESET") - results.add(CompressionResult(it.input, s0, s0, File(it.metadata.sourcePath))) - rcAapt2.assertNormalExitValue() - } - } - } - else -> { - logger.error("${CSI_RED}Command `${it.cmdline.joinToString(" ")}` exited with non-zero value ${rc.exitValue}$CSI_RESET") - results.add(CompressionResult(it.input, s0, s0, File(it.metadata.sourcePath))) - it.output.delete() - } - } - } - } - -} - diff --git a/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/CwebpCompressImages.kt b/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/CwebpCompressImages.kt deleted file mode 100644 index 209f690ff..000000000 --- a/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/CwebpCompressImages.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.didiglobal.booster.task.compression.cwebp - -import com.didiglobal.booster.compression.CompressionResult -import com.didiglobal.booster.compression.task.ActionData -import com.didiglobal.booster.kotlinx.CSI_RED -import com.didiglobal.booster.kotlinx.CSI_RESET -import org.gradle.api.tasks.CacheableTask -import org.gradle.api.tasks.OutputFiles -import java.io.File - -/** - * Represents a task for image compression using cwebp - * - * @author johnsonlee - */ -@CacheableTask -internal abstract class CwebpCompressImages : AbstractCwebpCompressImages() { - - @get:OutputFiles - val compressedImages: Collection - get() = images() - - override fun compress(filter: (File) -> Boolean) { - val cwebp = compressor.canonicalPath - images().parallelStream().filter(this::includes).filter(filter).map { input -> - val output = File(input.canonicalPath.substringBeforeLast('.') + ".webp") - ActionData(input, output, listOf(cwebp, "-mt", "-quiet", "-q", options.quality.toString(), "-o", output.canonicalPath, input.canonicalPath)) - }.forEach { - val s0 = it.input.length() - val rc = project.exec { spec -> - spec.isIgnoreExitValue = true - spec.commandLine = it.cmdline - } - when (rc.exitValue) { - 0 -> { - val s1 = it.output.length() - if (s1 > s0) { - results.add(CompressionResult(it.input, s0, s0, it.input)) - it.output.delete() - } else { - results.add(CompressionResult(it.input, s0, s1, it.input)) - it.input.delete() - } - } - else -> { - logger.error("${CSI_RED}Command `${it.cmdline.joinToString(" ")}` exited with non-zero value ${rc.exitValue}$CSI_RESET") - results.add(CompressionResult(it.input, s0, s0, it.input)) - it.output.delete() - } - } - } - } - -} - diff --git a/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/CwebpCompressOpaqueFlatImages.kt b/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/CwebpCompressOpaqueFlatImages.kt deleted file mode 100644 index 1b513b1c1..000000000 --- a/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/CwebpCompressOpaqueFlatImages.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.didiglobal.booster.task.compression.cwebp - -import org.gradle.api.tasks.CacheableTask -import java.io.File - -/** - * Represents a task for compiled image compression using cwebp - * - * @author johnsonlee - */ -@CacheableTask -internal abstract class CwebpCompressOpaqueFlatImages : CwebpCompressFlatImages() { - - override fun compress(filter: (File) -> Boolean) = super.compress { true } - -} - diff --git a/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/CwebpCompressOpaqueImages.kt b/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/CwebpCompressOpaqueImages.kt deleted file mode 100644 index 355db517c..000000000 --- a/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/CwebpCompressOpaqueImages.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.didiglobal.booster.task.compression.cwebp - -import org.gradle.api.tasks.CacheableTask -import java.awt.image.BufferedImage -import java.io.File -import javax.imageio.IIOException -import javax.imageio.ImageIO - -/** - * Represents a task for image compression using cwebp - * - * @author johnsonlee - */ -@CacheableTask -internal abstract class CwebpCompressOpaqueImages : CwebpCompressImages() { - - override fun compress(filter: (File) -> Boolean) = super.compress { true } - -} - -internal fun File.hasNotAlpha() = !hasAlpha() - -internal fun File.hasAlpha() = try { - ImageIO.read(this).let { - it.colorModel.hasAlpha() && it.hasAlpha() - } -} catch (e: IIOException) { - throw IIOException("${e.message}: ${this.canonicalPath}", e.cause) -} - -internal fun BufferedImage.hasAlpha(): Boolean { - for (x in 0 until width step 3) { - for (y in 0 until height step 3) { - if (0xff != ((getRGB(x, y) shr 24) and 0xff)) { - return true - } - } - } - return false -} - diff --git a/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/CwebpCompressionVariantProcessor.kt b/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/CwebpCompressionVariantProcessor.kt deleted file mode 100644 index 058a7ec9d..000000000 --- a/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/CwebpCompressionVariantProcessor.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.didiglobal.booster.task.compression.cwebp - -import com.android.build.gradle.api.BaseVariant -import com.didiglobal.booster.compression.CompressionResults -import com.didiglobal.booster.compression.generateReport -import com.didiglobal.booster.compression.isFlatPngExceptRaw -import com.didiglobal.booster.compression.isPngExceptRaw -import com.didiglobal.booster.gradle.isAapt2Enabled -import com.didiglobal.booster.gradle.mergeResourcesTaskProvider -import com.didiglobal.booster.gradle.mergedRes -import com.didiglobal.booster.gradle.project -import com.didiglobal.booster.kotlinx.Wildcard -import com.didiglobal.booster.kotlinx.search -import com.didiglobal.booster.task.spi.VariantProcessor -import com.google.auto.service.AutoService - -/** - * @author johnsonlee - */ -@AutoService(VariantProcessor::class) -class CwebpCompressionVariantProcessor : VariantProcessor { - - override fun process(variant: BaseVariant) { - val project = variant.project - val results = CompressionResults() - val ignores = project.findProperty(PROPERTY_IGNORES)?.toString()?.trim()?.split(',')?.map { - Wildcard(it) - }?.toSet() ?: emptySet() - - Cwebp.get(variant)?.newCompressionTaskCreator()?.createCompressionTask(variant, results, "resources", { - variant.mergedRes.search(if (project.isAapt2Enabled) ::isFlatPngExceptRaw else ::isPngExceptRaw) - }, ignores, variant.mergeResourcesTaskProvider)?.configure { - it.doLast { - results.generateReport(variant, Build.ARTIFACT) - } - } - } - -} - -private val PROPERTY_PREFIX = Build.ARTIFACT.replace('-', '.') - -private val PROPERTY_IGNORES = "$PROPERTY_PREFIX.ignores" \ No newline at end of file diff --git a/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/LauncherIconHandler.kt b/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/LauncherIconHandler.kt deleted file mode 100644 index 6fc5817b4..000000000 --- a/booster-task-compression-cwebp/src/main/kotlin/com/didiglobal/booster/task/compression/cwebp/LauncherIconHandler.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.didiglobal.booster.task.compression.cwebp - -import org.xml.sax.Attributes -import org.xml.sax.helpers.DefaultHandler - -/** - * Represents a handler for launcher icon parsing - * - * @author johnsonlee - */ -internal class LauncherIconHandler : DefaultHandler() { - - private val _icons = mutableSetOf() - - val icons: Set - get() = _icons - - override fun startElement(uri: String, localName: String, qName: String, attributes: Attributes) { - when (qName) { - "application" -> { - attributes.getValue("android:icon")?.let { - _icons.add(it.substringAfter('@')) - } - attributes.getValue("android:roundIcon")?.let { - _icons.add(it.substringAfter('@')) - } - } - } - } - -} diff --git a/booster-task-compression-cwebp/src/main/resources/bin/linux/x64/cwebp b/booster-task-compression-cwebp/src/main/resources/bin/linux/x64/cwebp deleted file mode 100644 index 36052a4b0..000000000 Binary files a/booster-task-compression-cwebp/src/main/resources/bin/linux/x64/cwebp and /dev/null differ diff --git a/booster-task-compression-cwebp/src/main/resources/bin/macosx/arm64/cwebp b/booster-task-compression-cwebp/src/main/resources/bin/macosx/arm64/cwebp deleted file mode 100755 index 61df9108a..000000000 Binary files a/booster-task-compression-cwebp/src/main/resources/bin/macosx/arm64/cwebp and /dev/null differ diff --git a/booster-task-compression-cwebp/src/main/resources/bin/macosx/x64/10.12/cwebp b/booster-task-compression-cwebp/src/main/resources/bin/macosx/x64/10.12/cwebp deleted file mode 100644 index 767a6ed48..000000000 Binary files a/booster-task-compression-cwebp/src/main/resources/bin/macosx/x64/10.12/cwebp and /dev/null differ diff --git a/booster-task-compression-cwebp/src/main/resources/bin/macosx/x64/10.13/cwebp b/booster-task-compression-cwebp/src/main/resources/bin/macosx/x64/10.13/cwebp deleted file mode 100644 index c33de856f..000000000 Binary files a/booster-task-compression-cwebp/src/main/resources/bin/macosx/x64/10.13/cwebp and /dev/null differ diff --git a/booster-task-compression-cwebp/src/main/resources/bin/macosx/x64/10.14/cwebp b/booster-task-compression-cwebp/src/main/resources/bin/macosx/x64/10.14/cwebp deleted file mode 100644 index 98bc04517..000000000 Binary files a/booster-task-compression-cwebp/src/main/resources/bin/macosx/x64/10.14/cwebp and /dev/null differ diff --git a/booster-task-compression-cwebp/src/main/resources/bin/macosx/x64/10.15/cwebp b/booster-task-compression-cwebp/src/main/resources/bin/macosx/x64/10.15/cwebp deleted file mode 100755 index b6c6c0f7a..000000000 Binary files a/booster-task-compression-cwebp/src/main/resources/bin/macosx/x64/10.15/cwebp and /dev/null differ diff --git a/booster-task-compression-cwebp/src/main/resources/bin/windows/x64/cwebp.exe b/booster-task-compression-cwebp/src/main/resources/bin/windows/x64/cwebp.exe deleted file mode 100644 index d95016c95..000000000 Binary files a/booster-task-compression-cwebp/src/main/resources/bin/windows/x64/cwebp.exe and /dev/null differ diff --git a/booster-task-compression-cwebp/src/test/kotlin/com/didiglobal/booster/task/compression/cwebp/CwebpProviderTest.kt b/booster-task-compression-cwebp/src/test/kotlin/com/didiglobal/booster/task/compression/cwebp/CwebpProviderTest.kt deleted file mode 100644 index 8b43d88f3..000000000 --- a/booster-task-compression-cwebp/src/test/kotlin/com/didiglobal/booster/task/compression/cwebp/CwebpProviderTest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.didiglobal.booster.task.compression.cwebp - -import com.didiglobal.booster.command.CommandService -import com.didiglobal.booster.kotlinx.OS -import kotlin.test.Test -import kotlin.test.assertNotNull - -class CwebpProviderTest { - - @Test - fun `load cwebp by spi`() { - val cwebp = CommandService.get("cwebp${OS.executableSuffix}") - assertNotNull(cwebp) - println(cwebp.location) - } - -} \ No newline at end of file diff --git a/booster-task-compression-pngquant/README.md b/booster-task-compression-pngquant/README.md deleted file mode 100644 index ffa6ccad4..000000000 --- a/booster-task-compression-pngquant/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# booster-task-compression-pngquant - -This module is used for assets and resource compression using `pngquant` - -- If `pngquant` has been installed, then use `pngquant` -- otherwise, do not compress any resources - -## Properties - -The following table shows the properties that transformer supports: - -| Property | Description | Example | -| -------------------------------------------------- | ----------------------------------------- | ------------------------------------------- | -| `booster.task.compression.pngquant.option.quality` | compression quality (this default is 80) | | -| `booster.task.compression.pngquant.option.speed` | compression speed (the default is 3) | | -| `booster.task.compression.pngquant.ignores` | ignore wildcards (separated by comma) | `mipmap/ic_launcher*,drawable/ic_launcher*` | - -## Using `pngquant` - -```bash -./gradlew assembleDebug \ - -Pbooster.task.compression.pngquant.option.quality=75 \ - -Pbooster.task.compression.pngquant.option.speed=1 -``` - -or configured in the `gradle.properties`: - -```properties -booster.task.compression.pngquant.option.quality=75 -booster.task.compression.pngquant.option.speed=1 -``` diff --git a/booster-task-compression-pngquant/build.gradle b/booster-task-compression-pngquant/build.gradle deleted file mode 100644 index bdcc99529..000000000 --- a/booster-task-compression-pngquant/build.gradle +++ /dev/null @@ -1,11 +0,0 @@ -apply from: "$rootDir/gradle/booster.gradle" - -dependencies { - kapt "com.google.auto.service:auto-service:1.0" - implementation project(':booster-annotations') - implementation project(':booster-task-compression') - compileOnly 'com.android.tools.build:gradle:4.0.0' - compileOnly 'com.android.tools.build:builder:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' - testCompileOnly 'com.android.tools.build:builder:4.0.0' -} diff --git a/booster-task-compression-pngquant/src/main/kotlin/com/didiglobal/booster/task/compression/pngquant/AbstractPngquantCompressImages.kt b/booster-task-compression-pngquant/src/main/kotlin/com/didiglobal/booster/task/compression/pngquant/AbstractPngquantCompressImages.kt deleted file mode 100644 index b4e456aab..000000000 --- a/booster-task-compression-pngquant/src/main/kotlin/com/didiglobal/booster/task/compression/pngquant/AbstractPngquantCompressImages.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.didiglobal.booster.task.compression.pngquant - -import com.didiglobal.booster.compression.task.CompressImages -import com.didiglobal.booster.gradle.getProperty -import org.gradle.api.tasks.TaskAction - -/** - * Represents an abstraction of pngquant compression task - * - * @author johnsonlee - */ -abstract class AbstractPngquantCompressImages: CompressImages() { - - @TaskAction - fun run() { - this.options = PngquantOptions( - project.getProperty(PROPERTY_OPTION_QUALITY, 80), - project.getProperty(PROPERTY_OPTION_SPEED, 3) - ) - compress() - } - - protected abstract fun compress() - -} \ No newline at end of file diff --git a/booster-task-compression-pngquant/src/main/kotlin/com/didiglobal/booster/task/compression/pngquant/Pngquant.kt b/booster-task-compression-pngquant/src/main/kotlin/com/didiglobal/booster/task/compression/pngquant/Pngquant.kt deleted file mode 100644 index 8ddfec8d0..000000000 --- a/booster-task-compression-pngquant/src/main/kotlin/com/didiglobal/booster/task/compression/pngquant/Pngquant.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.didiglobal.booster.task.compression.pngquant - -import com.android.build.gradle.api.BaseVariant -import com.didiglobal.booster.command.CommandService -import com.didiglobal.booster.compression.CompressionTaskCreatorFactory -import com.didiglobal.booster.compression.CompressionTool -import com.didiglobal.booster.compression.SimpleCompressionTaskCreator -import com.didiglobal.booster.kotlinx.OS -import com.didiglobal.booster.task.compression.pngquant.Pngquant.Companion.PROGRAM - -/** - * Represents utility class for pngquant operation - * - * @author johnsonlee - */ -internal class Pngquant : CompressionTool(CommandService.get(PNGQUANT)), CompressionTaskCreatorFactory { - - override fun newCompressionTaskCreator() = SimpleCompressionTaskCreator(this) { aapt2 -> - if (aapt2) PngquantCompressFlatImages::class else PngquantCompressImages::class - } - - companion object { - - const val PROGRAM = "pngquant" - - fun get(@Suppress("UNUSED_PARAMETER") variant: BaseVariant): Pngquant? { - return Pngquant() - } - - } - -} - -private val PNGQUANT = "$PROGRAM${OS.executableSuffix}" - -private val PROPERTY_PREFIX = Build.ARTIFACT.replace('-', '.') -internal val PROPERTY_BIN = "${PROPERTY_PREFIX}.bin" -internal val PROPERTY_OPTION_QUALITY = "${PROPERTY_PREFIX}.option.quality" -internal val PROPERTY_OPTION_SPEED = "${PROPERTY_PREFIX}.option.speed" diff --git a/booster-task-compression-pngquant/src/main/kotlin/com/didiglobal/booster/task/compression/pngquant/PngquantCompressFlatImages.kt b/booster-task-compression-pngquant/src/main/kotlin/com/didiglobal/booster/task/compression/pngquant/PngquantCompressFlatImages.kt deleted file mode 100644 index af796b9fe..000000000 --- a/booster-task-compression-pngquant/src/main/kotlin/com/didiglobal/booster/task/compression/pngquant/PngquantCompressFlatImages.kt +++ /dev/null @@ -1,86 +0,0 @@ -package com.didiglobal.booster.task.compression.pngquant - -import com.android.SdkConstants.DOT_PNG -import com.android.SdkConstants.FD_RES -import com.android.SdkConstants.FD_RES_DRAWABLE -import com.android.SdkConstants.FD_RES_MIPMAP -import com.android.builder.model.AndroidProject.FD_INTERMEDIATES -import com.android.sdklib.BuildToolInfo -import com.didiglobal.booster.aapt2.metadata -import com.didiglobal.booster.compression.CompressionResult -import com.didiglobal.booster.compression.task.Aapt2ActionData -import com.didiglobal.booster.gradle.buildTools -import com.didiglobal.booster.gradle.project -import com.didiglobal.booster.kotlinx.CSI_RED -import com.didiglobal.booster.kotlinx.CSI_RESET -import com.didiglobal.booster.kotlinx.file -import org.gradle.api.tasks.CacheableTask -import org.gradle.api.tasks.OutputDirectory -import java.io.File - -/** - * Represents a task for compiled image compression using pngquant - * - * @author johnsonlee - */ -@CacheableTask -internal abstract class PngquantCompressFlatImages : AbstractPngquantCompressImages() { - - private val intermediates: File - get() = variant.project.buildDir.file(FD_INTERMEDIATES) - - @get:OutputDirectory - val compressedRes: File - get() = intermediates.file("compressed_${FD_RES}_pngquant", variant.dirName, this.name) - - @get:OutputDirectory - val compiledRes: File - get() = intermediates.file("compiled_${FD_RES}_pngquant", variant.dirName, this.name) - - override fun compress() { - val pngquant = this.compressor.canonicalPath - val aapt2 = variant.buildTools.getPath(BuildToolInfo.PathId.AAPT2) - - compiledRes.mkdirs() - compressedRes.file(FD_RES_MIPMAP).mkdirs() - compressedRes.file(FD_RES_DRAWABLE).mkdirs() - - images().parallelStream().map { - it to it.metadata - }.filter(this::includes).map { - val output = compressedRes.file("${it.second.resourcePath.substringBeforeLast('.')}$DOT_PNG") - Aapt2ActionData(it.first, it.second, output, - listOf(pngquant, "--strip", "--skip-if-larger", "-f", "-o", output.canonicalPath, "-s", "${options.speed}", "-Q", "${options.quality}-100", it.second.sourcePath), - listOf(aapt2, "compile", "-o", it.first.parent, output.canonicalPath)) - }.forEach { - it.output.parentFile.mkdirs() - val s0 = File(it.metadata.sourcePath).length() - val rc = project.exec { spec -> - spec.isIgnoreExitValue = true - spec.commandLine = it.cmdline - } - when (rc.exitValue) { - 0 -> { - val s1 = it.output.length() - val rcAapt2 = project.exec { spec -> - spec.isIgnoreExitValue = true - spec.commandLine = it.aapt2 - } - - if (0 == rcAapt2.exitValue) { - results.add(CompressionResult(it.input, s0, s1, File(it.metadata.sourcePath))) - } else { - logger.error("${CSI_RED}Command `${it.aapt2.joinToString(" ")}` exited with non-zero value ${rc.exitValue}$CSI_RESET") - results.add(CompressionResult(it.input, s0, s0, File(it.metadata.sourcePath))) - rcAapt2.assertNormalExitValue() - } - } - else -> { - logger.error("${CSI_RED}Command `${it.cmdline.joinToString(" ")}` exited with non-zero value ${rc.exitValue}$CSI_RESET") - results.add(CompressionResult(it.input, s0, s0, File(it.metadata.sourcePath))) - } - } - } - } - -} diff --git a/booster-task-compression-pngquant/src/main/kotlin/com/didiglobal/booster/task/compression/pngquant/PngquantCompressImages.kt b/booster-task-compression-pngquant/src/main/kotlin/com/didiglobal/booster/task/compression/pngquant/PngquantCompressImages.kt deleted file mode 100644 index bcc4283dd..000000000 --- a/booster-task-compression-pngquant/src/main/kotlin/com/didiglobal/booster/task/compression/pngquant/PngquantCompressImages.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.didiglobal.booster.task.compression.pngquant - -import com.android.SdkConstants.DOT_PNG -import com.didiglobal.booster.compression.CompressionResult -import com.didiglobal.booster.compression.task.ActionData -import com.didiglobal.booster.kotlinx.CSI_RED -import com.didiglobal.booster.kotlinx.CSI_RESET -import org.gradle.api.tasks.CacheableTask -import org.gradle.api.tasks.OutputFiles -import java.io.File - -/** - * Represents a task for image compression using pngquant - * - * @author johnsonlee - */ -@CacheableTask -internal abstract class PngquantCompressImages : AbstractPngquantCompressImages() { - - @get:OutputFiles - val compressedImages: Collection - get() = images() - - override fun compress() { - val pngquant = this.compressor.canonicalPath - - images().parallelStream().filter(this::includes).map { - ActionData(it, it, listOf(pngquant, "--strip", "--skip-if-larger", "-f", "--ext", DOT_PNG, "-s", "${options.speed}", "-Q", "${options.quality}-100", it.canonicalPath)) - }.forEach { - val s0 = it.input.length() - val rc = project.exec { spec -> - spec.isIgnoreExitValue = true - spec.commandLine = it.cmdline - } - when (rc.exitValue) { - 0 -> { - val s1 = it.input.length() - results.add(CompressionResult(it.input, s0, s1, it.input)) - } - else -> { - logger.error("${CSI_RED}Command `${it.cmdline.joinToString(" ")}` exited with non-zero value ${rc.exitValue}$CSI_RESET") - results.add(CompressionResult(it.input, s0, s0, it.input)) - } - } - } - } - -} diff --git a/booster-task-compression-pngquant/src/main/kotlin/com/didiglobal/booster/task/compression/pngquant/PngquantCompressionVariantProcessor.kt b/booster-task-compression-pngquant/src/main/kotlin/com/didiglobal/booster/task/compression/pngquant/PngquantCompressionVariantProcessor.kt deleted file mode 100644 index 3d2f63eb9..000000000 --- a/booster-task-compression-pngquant/src/main/kotlin/com/didiglobal/booster/task/compression/pngquant/PngquantCompressionVariantProcessor.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.didiglobal.booster.task.compression.pngquant - -import com.android.build.gradle.api.BaseVariant -import com.didiglobal.booster.annotations.Priority -import com.didiglobal.booster.compression.CompressionResults -import com.didiglobal.booster.compression.generateReport -import com.didiglobal.booster.compression.isFlatPngExceptRaw -import com.didiglobal.booster.compression.isPngExceptRaw -import com.didiglobal.booster.compression.task.CompressImages -import com.didiglobal.booster.gradle.isAapt2Enabled -import com.didiglobal.booster.gradle.mergeResourcesTaskProvider -import com.didiglobal.booster.gradle.mergedRes -import com.didiglobal.booster.gradle.project -import com.didiglobal.booster.kotlinx.Wildcard -import com.didiglobal.booster.kotlinx.search -import com.didiglobal.booster.task.spi.VariantProcessor -import com.google.auto.service.AutoService - -/** - * @author johnsonlee - */ -@AutoService(VariantProcessor::class) -@Priority(1) -class PngquantCompressionVariantProcessor : VariantProcessor { - - override fun process(variant: BaseVariant) { - val project = variant.project - val results = CompressionResults() - val ignores = project.findProperty(PROPERTY_IGNORES)?.toString()?.trim()?.split(',')?.map { - Wildcard(it) - }?.toSet() ?: emptySet() - - Pngquant.get(variant)?.newCompressionTaskCreator()?.createCompressionTask(variant, results, "resources", { - variant.mergedRes.search(if (project.isAapt2Enabled) ::isFlatPngExceptRaw else ::isPngExceptRaw) - }, ignores, variant.mergeResourcesTaskProvider)?.configure { task -> - variant.project.tasks.withType(CompressImages::class.java).filter { - it.name != task.name && it.variant.name == variant.name - }.takeIf { - it.isNotEmpty() - }?.let { - task.dependsOn(*it.toTypedArray()) - } - task.doLast { - results.generateReport(variant, Build.ARTIFACT) - } - } - } - -} - -private val PROPERTY_PREFIX = Build.ARTIFACT.replace('-', '.') - -private val PROPERTY_IGNORES = "$PROPERTY_PREFIX.ignores" \ No newline at end of file diff --git a/booster-task-compression-pngquant/src/main/kotlin/com/didiglobal/booster/task/compression/pngquant/PngquantOptions.kt b/booster-task-compression-pngquant/src/main/kotlin/com/didiglobal/booster/task/compression/pngquant/PngquantOptions.kt deleted file mode 100644 index 3d0942302..000000000 --- a/booster-task-compression-pngquant/src/main/kotlin/com/didiglobal/booster/task/compression/pngquant/PngquantOptions.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.didiglobal.booster.task.compression.pngquant - -import com.didiglobal.booster.compression.CompressionOptions - -class PngquantOptions(quality: Int, val speed: Int) : CompressionOptions(quality = quality) diff --git a/booster-task-compression-processed-res/README.md b/booster-task-compression-processed-res/README.md deleted file mode 100644 index dbf1adbbb..000000000 --- a/booster-task-compression-processed-res/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# booster-task-compression-processed-res - -This module is used for *resources-${variant}.ap_* file compression diff --git a/booster-task-compression-processed-res/build.gradle b/booster-task-compression-processed-res/build.gradle deleted file mode 100644 index 42eaccc1b..000000000 --- a/booster-task-compression-processed-res/build.gradle +++ /dev/null @@ -1,10 +0,0 @@ -apply from: "$rootDir/gradle/booster.gradle" - -dependencies { - kapt "com.google.auto.service:auto-service:1.0" - implementation project(':booster-task-compression') - compileOnly 'com.android.tools.build:gradle:4.0.0' - compileOnly 'com.android.tools.build:builder:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' - testCompileOnly 'com.android.tools.build:builder:4.0.0' -} diff --git a/booster-task-compression-processed-res/src/main/kotlin/com/didiglobal/booster/task/compression/processed/res/ProcessedResourcesCompressionVariantProcessor.kt b/booster-task-compression-processed-res/src/main/kotlin/com/didiglobal/booster/task/compression/processed/res/ProcessedResourcesCompressionVariantProcessor.kt deleted file mode 100644 index 06a949ebf..000000000 --- a/booster-task-compression-processed-res/src/main/kotlin/com/didiglobal/booster/task/compression/processed/res/ProcessedResourcesCompressionVariantProcessor.kt +++ /dev/null @@ -1,160 +0,0 @@ -package com.didiglobal.booster.task.compression.processed.res - -import com.android.SdkConstants -import com.android.SdkConstants.DOT_PNG -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.internal.tasks.factory.dependsOn -import com.didiglobal.booster.BOOSTER -import com.didiglobal.booster.compression.CompressionReport -import com.didiglobal.booster.compression.CompressionResult -import com.didiglobal.booster.compression.CompressionResults -import com.didiglobal.booster.gradle.processResTaskProvider -import com.didiglobal.booster.gradle.processedRes -import com.didiglobal.booster.gradle.project -import com.didiglobal.booster.kotlinx.file -import com.didiglobal.booster.kotlinx.search -import com.didiglobal.booster.kotlinx.touch -import com.didiglobal.booster.task.spi.VariantProcessor -import com.didiglobal.booster.transform.util.transform -import com.google.auto.service.AutoService -import org.apache.commons.compress.archivers.zip.ZipArchiveEntry -import org.gradle.api.DefaultTask -import org.gradle.api.tasks.Internal -import org.gradle.api.tasks.TaskAction -import java.io.File -import java.text.DecimalFormat -import java.util.zip.ZipEntry -import java.util.zip.ZipFile - - -/** - * Represents a variant processor for processed resources compression - * - * @author johnsonlee - */ -@AutoService(VariantProcessor::class) -class ProcessedResourcesCompressionVariantProcessor : VariantProcessor { - - override fun process(variant: BaseVariant) { - @Suppress("DEPRECATION") - val compress = variant.project.tasks.register("compress${variant.name.capitalize()}ProcessedRes", CompressProcessedRes::class.java) { - it.group = BOOSTER - it.description = "Compress the processed resource file for ${variant.name}" - it.variant = variant - } - variant.processResTaskProvider?.let { processRes -> - compress.dependsOn(processRes) - processRes.configure { - it.finalizedBy(compress) - } - } - } - -} - -internal abstract class CompressProcessedRes : DefaultTask() { - - @get:Internal - lateinit var variant: BaseVariant - - @TaskAction - fun compress() { - val results = CompressionResults() - variant.compressProcessedRes(results) - variant.generateReport(results) - } - -} - -private fun BaseVariant.compressProcessedRes(results: CompressionResults) { - val files = processedRes.search { - it.name.startsWith(SdkConstants.FN_RES_BASE) && it.extension == SdkConstants.EXT_RES - } - files.parallelStream().forEach { ap_ -> - val s0 = ap_.length() - ap_.repack { - !NO_COMPRESS.contains(it.name.substringAfterLast('.')) - } - val s1 = ap_.length() - results.add(CompressionResult(ap_, s0, s1, ap_)) - } -} - -private fun File.repack(shouldCompress: (ZipEntry) -> Boolean) { - val dest = File.createTempFile(SdkConstants.FN_RES_BASE + SdkConstants.RES_QUALIFIER_SEP, SdkConstants.DOT_RES) - - ZipFile(this).use { - it.transform(dest, { origin: ZipEntry -> - ZipArchiveEntry(origin).apply { - method = if (shouldCompress(origin)) ZipEntry.DEFLATED else origin.method - } - }) - } - - if (this.delete()) { - if (!dest.renameTo(this)) { - dest.copyTo(this, true) - } - } -} - -/** - * - * Generates report with format like the following: - * - * reduction percentage | file path | reduced size - */ -private fun BaseVariant.generateReport(results: CompressionResults) { - val base = project.buildDir.toURI() - val table = results.map { - val delta = it.second - it.third - CompressionReport( - base.relativize(it.first.toURI()).path, - it.second, - it.third, - delta, - if (delta == 0L) "0" else decimal(delta), - if (delta == 0L) "0%" else percentage((delta).toDouble() * 100 / it.second), - decimal(it.second), - it.fourth - ) - } - val maxWith1 = table.maxOfOrNull { it.first.length } ?: 0 - val maxWith5 = table.maxOfOrNull { it.fifth.length } ?: 0 - val maxWith6 = table.maxOfOrNull { it.sixth.length } ?: 0 - val maxWith7 = table.maxOfOrNull { it.seventh.length } ?: 0 - val fullWith = maxWith1 + maxWith5 + maxWith6 + 8 - - project.buildDir.file("reports", Build.ARTIFACT, name, "report.txt").touch().printWriter().use { logger -> - // sort by reduced size and original size - table.sortedWith(compareByDescending { - it.fourth - }.thenByDescending { - it.second - }).forEach { - logger.println("${it.sixth.padStart(maxWith6)} ${it.first.padEnd(maxWith1)} ${it.fifth.padStart(maxWith5)} ${it.seventh.padStart(maxWith7)} ${it.eighth}") - } - logger.println("-".repeat(maxWith1 + maxWith5 + maxWith6 + 2)) - logger.println(" TOTAL ${decimal(table.sumOf { it.fourth.toDouble() }).padStart(fullWith - 13)}") - } - -} - -internal val NO_COMPRESS = setOf( - "jpg", "jpeg", "png", "gif", "webp", - "wav", "mp2", "mp3", "ogg", "aac", - "mpg", "mpeg", "mid", "midi", "smf", "jet", - "rtttl", "imy", "xmf", "mp4", "m4a", - "m4v", "3gp", "3gpp", "3g2", "3gpp2", - "amr", "awb", "wma", "wmv", "webm", "mkv", "arsc" -) - -internal val percentage: (Number) -> String = DecimalFormat("#,##0.00'%'")::format - -internal val decimal: (Number) -> String = DecimalFormat("#,##0")::format - -internal fun isPng(file: File): Boolean = file.name.endsWith(DOT_PNG, true) - && (file.name.length < 6 || !file.name.regionMatches(file.name.length - 6, ".9", 0, 2, true)) - -internal fun isFlatPng(file: File): Boolean = file.name.endsWith(".png.flat", true) - && (file.name.length < 11 || !file.name.regionMatches(file.name.length - 11, ".9", 0, 2, true)) diff --git a/booster-task-compression/README.md b/booster-task-compression/README.md deleted file mode 100644 index c8cfefcff..000000000 --- a/booster-task-compression/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# booster-task-compression - -This is a base module for assets and resource compression diff --git a/booster-task-compression/build.gradle b/booster-task-compression/build.gradle deleted file mode 100644 index fe3f6b7ae..000000000 --- a/booster-task-compression/build.gradle +++ /dev/null @@ -1,12 +0,0 @@ -apply from: "$rootDir/gradle/booster.gradle" - -dependencies { - kapt "com.google.auto.service:auto-service:1.0" - api project(':booster-aapt2') - api project(':booster-api') - api project(':booster-command') - compileOnly 'com.android.tools.build:gradle:4.0.0' - compileOnly 'com.android.tools.build:builder:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' - testCompileOnly 'com.android.tools.build:builder:4.0.0' -} diff --git a/booster-task-compression/packages-zh-CN.md b/booster-task-compression/packages-zh-CN.md deleted file mode 100644 index 9f9178e95..000000000 --- a/booster-task-compression/packages-zh-CN.md +++ /dev/null @@ -1,8 +0,0 @@ -# Package com.didiglobal.booster.compression - -提供了图像资源压缩相关的 API - -# Package com.didiglobal.booster.compression.task - -提供了图像资源压缩任务基类,允许开发者对其进行扩展 - diff --git a/booster-task-compression/src/main/kotlin/com/didiglobal/booster/compression/CompressionOptions.kt b/booster-task-compression/src/main/kotlin/com/didiglobal/booster/compression/CompressionOptions.kt deleted file mode 100644 index 0f539dde2..000000000 --- a/booster-task-compression/src/main/kotlin/com/didiglobal/booster/compression/CompressionOptions.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.didiglobal.booster.compression - -open class CompressionOptions( - val quality: Int -) \ No newline at end of file diff --git a/booster-task-compression/src/main/kotlin/com/didiglobal/booster/compression/CompressionReport.kt b/booster-task-compression/src/main/kotlin/com/didiglobal/booster/compression/CompressionReport.kt deleted file mode 100644 index c0cc064f2..000000000 --- a/booster-task-compression/src/main/kotlin/com/didiglobal/booster/compression/CompressionReport.kt +++ /dev/null @@ -1,92 +0,0 @@ -package com.didiglobal.booster.compression - -import com.android.SdkConstants -import com.android.build.gradle.api.BaseVariant -import com.didiglobal.booster.gradle.getReport -import com.didiglobal.booster.gradle.project -import com.didiglobal.booster.kotlinx.Octuple -import com.didiglobal.booster.kotlinx.Quadruple -import com.didiglobal.booster.kotlinx.touch -import java.io.File -import java.text.DecimalFormat -import java.util.concurrent.CopyOnWriteArrayList - -/** - * - * Generates report with format like the following: - * - * reduction percentage | file path | reduced size - */ -fun CompressionResults.generateReport(variant: BaseVariant, artifact: String) { - val base = variant.project.buildDir.toURI() - val table = this.map { - val delta = it.second - it.third - CompressionReport( - base.relativize(it.first.toURI()).path, - it.second, - it.third, - delta, - if (delta == 0L) "0" else decimal(delta), - if (delta == 0L) "0%" else percentage((delta).toDouble() * 100 / it.second), - decimal(it.second), - it.fourth - ) - } - val maxWith1 = table.maxOfOrNull { it.first.length } ?: 0 - val maxWith5 = table.maxOfOrNull { it.fifth.length } ?: 0 - val maxWith6 = table.maxOfOrNull { it.sixth.length } ?: 0 - val maxWith7 = table.maxOfOrNull { it.seventh.length } ?: 0 - val fullWith = maxWith1 + maxWith5 + maxWith6 + 8 - - variant.getReport(artifact, "report.txt").touch().printWriter().use { logger -> - // sort by reduced size and original size - table.sortedWith(compareByDescending { - it.fourth - }.thenByDescending { - it.second - }).forEach { - logger.println("${it.sixth.padStart(maxWith6)} ${it.first.padEnd(maxWith1)} ${it.fifth.padStart(maxWith5)} ${it.seventh.padStart(maxWith7)} ${it.eighth}") - } - logger.println("-".repeat(maxWith1 + maxWith5 + maxWith6 + 2)) - logger.println(" TOTAL ${decimal(table.sumOf { it.fourth.toDouble() }).padStart((fullWith - 13).coerceAtLeast(0))}") - } - -} - -/** - * Compression Result - * - * 1. image file - * 2. original file size - * 3. current file size - * 4. original file path - */ -typealias CompressionResult = Quadruple - -typealias CompressionResults = CopyOnWriteArrayList - -/** - * 1. relative path - * 2. original size - * 3. compressed size - * 4. reduced size - * 5. formatted reduced size - * 6. reduction percentage - * 7. original size - * 8. original path - */ -typealias CompressionReport = Octuple - -val percentage: (Number) -> String = DecimalFormat("#,##0.00'%'")::format - -val decimal: (Number) -> String = DecimalFormat("#,##0")::format - -fun isPng(file: File): Boolean = file.name.endsWith(SdkConstants.DOT_PNG, true) - && (file.name.length < 6 || !file.name.regionMatches(file.name.length - 6, ".9", 0, 2, true)) - -fun isFlatPng(file: File): Boolean = file.name.endsWith(".png.flat", true) - && (file.name.length < 11 || !file.name.regionMatches(file.name.length - 11, ".9", 0, 2, true)) - -fun isPngExceptRaw(file: File) : Boolean = isPng(file) && file.parentFile.name != "raw" - -fun isFlatPngExceptRaw(file: File) : Boolean = isFlatPng(file) && !file.name.startsWith("raw_") diff --git a/booster-task-compression/src/main/kotlin/com/didiglobal/booster/compression/CompressionTaskCreator.kt b/booster-task-compression/src/main/kotlin/com/didiglobal/booster/compression/CompressionTaskCreator.kt deleted file mode 100644 index 34e656b20..000000000 --- a/booster-task-compression/src/main/kotlin/com/didiglobal/booster/compression/CompressionTaskCreator.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.didiglobal.booster.compression - -import com.android.build.gradle.api.BaseVariant -import com.didiglobal.booster.compression.task.CompressImages -import com.didiglobal.booster.kotlinx.Wildcard -import org.gradle.api.Task -import org.gradle.api.tasks.TaskProvider -import java.io.File -import kotlin.reflect.KClass - -/** - * Represents the creator of [CompressImages] - * - * @author johnsonlee - */ -interface CompressionTaskCreator { - - /** - * Returns the class of compression task - * - * @param aapt2 A value to determine if aapt2 enabled - */ - fun getCompressionTaskClass(aapt2: Boolean): KClass> - - /** - * Returns a task for compression - * - * @param variant The build variant - * @param results The compression results for report generating - * @param name The name of task - * @param supplier The image supplier - * @param deps The dependent tasks - */ - fun createCompressionTask( - variant: BaseVariant, - results: CompressionResults, - name: String, - supplier: () -> Collection, - vararg deps: TaskProvider - ): TaskProvider> = createCompressionTask(variant, results, name, supplier, emptySet(), *deps) - - /** - * Returns a task for compression - * - * @param variant The build variant - * @param results The compression results for report generating - * @param name The name of task - * @param supplier The image supplier - * @param ignores wildcard of the resource name which to be excluded - * @param deps The dependent tasks - */ - fun createCompressionTask( - variant: BaseVariant, - results: CompressionResults, - name: String, - supplier: () -> Collection, - ignores: Set = emptySet(), - vararg deps: TaskProvider - ): TaskProvider> - -} diff --git a/booster-task-compression/src/main/kotlin/com/didiglobal/booster/compression/CompressionTaskCreatorFactory.kt b/booster-task-compression/src/main/kotlin/com/didiglobal/booster/compression/CompressionTaskCreatorFactory.kt deleted file mode 100644 index c23ca8c28..000000000 --- a/booster-task-compression/src/main/kotlin/com/didiglobal/booster/compression/CompressionTaskCreatorFactory.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.didiglobal.booster.compression - -import com.didiglobal.booster.compression.CompressionTaskCreator - -/** - * Represents a factory of [CompressionTaskCreator] - * - * @author johnsonlee - */ -interface CompressionTaskCreatorFactory { - - fun newCompressionTaskCreator(): CompressionTaskCreator - -} - diff --git a/booster-task-compression/src/main/kotlin/com/didiglobal/booster/compression/CompressionTool.kt b/booster-task-compression/src/main/kotlin/com/didiglobal/booster/compression/CompressionTool.kt deleted file mode 100644 index dcf3ed739..000000000 --- a/booster-task-compression/src/main/kotlin/com/didiglobal/booster/compression/CompressionTool.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.didiglobal.booster.compression - -import com.didiglobal.booster.command.Command -import java.io.File - -/** - * Represents a compression tool - * - * @author johnsonlee - * - * @param command The command for image compression - */ -abstract class CompressionTool(val command: Command) : CompressionTaskCreatorFactory { - -} diff --git a/booster-task-compression/src/main/kotlin/com/didiglobal/booster/compression/SimpleCompressionTaskCreator.kt b/booster-task-compression/src/main/kotlin/com/didiglobal/booster/compression/SimpleCompressionTaskCreator.kt deleted file mode 100644 index 8ed8c6d11..000000000 --- a/booster-task-compression/src/main/kotlin/com/didiglobal/booster/compression/SimpleCompressionTaskCreator.kt +++ /dev/null @@ -1,92 +0,0 @@ -package com.didiglobal.booster.compression - -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.internal.tasks.factory.dependsOn -import com.didiglobal.booster.BOOSTER -import com.didiglobal.booster.command.CommandInstaller -import com.didiglobal.booster.compression.task.CompressImages -import com.didiglobal.booster.compression.task.MATCH_ALL_RESOURCES -import com.didiglobal.booster.compression.task.excludes -import com.didiglobal.booster.gradle.bundleResourcesTaskProvider -import com.didiglobal.booster.gradle.isAapt2Enabled -import com.didiglobal.booster.gradle.mergeResourcesTaskProvider -import com.didiglobal.booster.gradle.preBuildTaskProvider -import com.didiglobal.booster.gradle.processResTaskProvider -import com.didiglobal.booster.gradle.project -import com.didiglobal.booster.kotlinx.Wildcard -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.UnknownTaskException -import org.gradle.api.tasks.TaskProvider -import java.io.File -import kotlin.reflect.KClass - -/** - * Represents a simple implementation of [CompressionTaskCreator] - * - * @author johnsonlee - */ -class SimpleCompressionTaskCreator(private val tool: CompressionTool, private val compressor: (Boolean) -> KClass>) : CompressionTaskCreator { - - override fun getCompressionTaskClass(aapt2: Boolean) = compressor(aapt2) - - override fun createCompressionTask( - variant: BaseVariant, - results: CompressionResults, - name: String, - supplier: () -> Collection, - ignores: Set, - vararg deps: TaskProvider - ): TaskProvider> { - val project = variant.project - val aapt2 = project.isAapt2Enabled - val install = getCommandInstaller(variant) - - @Suppress("DEPRECATION") - return project.tasks.register("compress${variant.name.capitalize()}${name.capitalize()}With${tool.command.name.substringBefore('.').capitalize()}", getCompressionTaskClass(aapt2).java) { task -> - task.group = BOOSTER - task.description = "Compress image resources by ${tool.command.name} for ${variant.name}" - task.dependsOn(variant.preBuildTaskProvider.get()) - task.tool = tool - task.variant = variant - task.results = results - task.filter = if (ignores.isNotEmpty()) excludes(ignores) else MATCH_ALL_RESOURCES - task.images = lazy(supplier)::value - }.apply { - dependsOn(install) - deps.forEach { dependsOn(it) } - variant.processResTaskProvider?.dependsOn(this) - variant.bundleResourcesTaskProvider?.dependsOn(this) - } - } - - private fun getCommandInstaller(variant: BaseVariant): TaskProvider { - return variant.project.tasks.register(getInstallTaskName(variant.name)) { - it.group = BOOSTER - it.description = "Install ${tool.command.name} for ${variant.name}" - }.apply { - dependsOn(getCommandInstaller(variant.project)) - dependsOn(variant.mergeResourcesTaskProvider) - } - } - - private fun getCommandInstaller(project: Project): TaskProvider { - val name = getInstallTaskName() - return try { - project.tasks.named(name) - } catch (e: UnknownTaskException) { - null - } ?: project.tasks.register(name, CommandInstaller::class.java) { - it.group = BOOSTER - it.description = "Install ${tool.command.name}" - it.command = tool.command - } - } - - private fun getInstallTaskName(variant: String = ""): String { - @Suppress("DEPRECATION") - return "install${variant.capitalize()}${tool.command.name.substringBefore('.').capitalize()}" - } - -} - diff --git a/booster-task-compression/src/main/kotlin/com/didiglobal/booster/compression/task/CompressImages.kt b/booster-task-compression/src/main/kotlin/com/didiglobal/booster/compression/task/CompressImages.kt deleted file mode 100644 index d763a1f83..000000000 --- a/booster-task-compression/src/main/kotlin/com/didiglobal/booster/compression/task/CompressImages.kt +++ /dev/null @@ -1,93 +0,0 @@ -package com.didiglobal.booster.compression.task - -import com.android.build.gradle.api.BaseVariant -import com.didiglobal.booster.aapt2.Aapt2Container -import com.didiglobal.booster.aapt2.resourceName -import com.didiglobal.booster.command.Command -import com.didiglobal.booster.command.CommandInstaller -import com.didiglobal.booster.compression.CompressionOptions -import com.didiglobal.booster.compression.CompressionResult -import com.didiglobal.booster.compression.CompressionResults -import com.didiglobal.booster.compression.CompressionTool -import com.didiglobal.booster.kotlinx.Wildcard -import org.gradle.api.DefaultTask -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.Internal -import java.io.File - -/** - * Represents task for image compression - * - * @author johnsonlee - */ -abstract class CompressImages : DefaultTask() { - - @get:Internal - lateinit var variant: BaseVariant - - @get:Internal - lateinit var tool: CompressionTool - - @get:Internal - lateinit var results: CompressionResults - - @get:Internal - lateinit var options: T - - @get:Internal - lateinit var images: () -> Collection - - /** - * The resource path filter - */ - @get:Internal - var filter: ResourceNameFilter = MATCH_ALL_RESOURCES - - @get:Internal - val compressor: File - get() = project.tasks.withType(CommandInstaller::class.java).find { - it.command == tool.command - }!!.location - - @get:Input - val command: Command - get() = tool.command - - @get:Input - val variantName: String - get() = variant.name - - protected open fun includes(arg: Pair): Boolean { - val (input, metadata) = arg - return if (filter(metadata.resourceName)) true else false.also { - ignore(metadata.resourceName, input, File(metadata.sourcePath)) - } - } - - protected open fun includes(input: File): Boolean { - return if (filter(input.resourceName)) true else false.also { - ignore(input.resourceName, input, input) - } - } - - protected fun ignore(resName: String, dest: File, src: File) { - val s0 = dest.length() - results.add(CompressionResult(dest, s0, s0, src)) - logger.info("${tool.command.name}: exclude $resName $dest => $src") - } - -} - -internal typealias ResourceNameFilter = (String) -> Boolean - -internal val MATCH_ALL_RESOURCES: ResourceNameFilter = { true } - -internal fun excludes(ignores: Set): ResourceNameFilter = { res -> - ignores.none { - it.matches(res) - } -} - -data class ActionData(val input: File, val output: File, val cmdline: List) - -data class Aapt2ActionData(val input: File, val metadata: Aapt2Container.Metadata, val output: File, val cmdline: List, val aapt2: List) diff --git a/booster-task-compression/src/test/kotlin/com/didiglobal/booster/task/compression/FileNameTest.kt b/booster-task-compression/src/test/kotlin/com/didiglobal/booster/task/compression/FileNameTest.kt deleted file mode 100644 index 6fc3a4135..000000000 --- a/booster-task-compression/src/test/kotlin/com/didiglobal/booster/task/compression/FileNameTest.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.didiglobal.booster.task.compression - -import com.didiglobal.booster.compression.isFlatPng -import com.didiglobal.booster.compression.isPng -import java.io.File -import kotlin.test.Test -import kotlin.test.assertFalse -import kotlin.test.assertTrue - -class FileNameTest { - - @Test - fun `test png name`() { - assertTrue(isPng(File("abc_text.png"))) - assertFalse(isPng(File("abc_text.9.png"))) - - assertTrue(isFlatPng(File("drawable/abc_text.png.flat"))) - assertFalse(isFlatPng(File("drawable/abc_text.9.png.flat"))) - } - -} diff --git a/booster-task-graph/build.gradle b/booster-task-graph/build.gradle index 5d2ca9637..02686df3b 100644 --- a/booster-task-graph/build.gradle +++ b/booster-task-graph/build.gradle @@ -6,8 +6,8 @@ dependencies { implementation project(':booster-graph-dot') implementation project(':booster-command') implementation 'io.johnsonlee:once:1.2.0' - compileOnly 'com.android.tools.build:gradle:4.0.0' + compileOnly 'com.android.tools.build:gradle:8.0.0' compileOnly 'com.android.tools.build:builder:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' + testCompileOnly 'com.android.tools.build:gradle:8.0.0' testCompileOnly 'com.android.tools.build:builder:4.0.0' } diff --git a/booster-task-graph/src/main/kotlin/com/didiglobal/booster/task/graph/GraphVariantProcessor.kt b/booster-task-graph/src/main/kotlin/com/didiglobal/booster/task/graph/GraphVariantProcessor.kt index 4decadf4e..66a970749 100644 --- a/booster-task-graph/src/main/kotlin/com/didiglobal/booster/task/graph/GraphVariantProcessor.kt +++ b/booster-task-graph/src/main/kotlin/com/didiglobal/booster/task/graph/GraphVariantProcessor.kt @@ -1,10 +1,7 @@ package com.didiglobal.booster.task.graph -import com.android.build.gradle.api.BaseVariant -import com.didiglobal.booster.gradle.getResolvedArtifactResults -import com.didiglobal.booster.gradle.getTaskName -import com.didiglobal.booster.gradle.getUpstreamProjects -import com.didiglobal.booster.gradle.project +import com.android.build.api.variant.Variant +import com.didiglobal.booster.gradle.* import com.didiglobal.booster.graph.Edge import com.didiglobal.booster.graph.Graph import com.didiglobal.booster.graph.dot.DotGraph @@ -12,16 +9,14 @@ import com.didiglobal.booster.kotlinx.file import com.didiglobal.booster.task.spi.VariantProcessor import com.google.auto.service.AutoService import io.johnsonlee.once.Once -import org.gradle.api.Project -import org.gradle.api.artifacts.component.ProjectComponentIdentifier -import java.util.Stack +import java.util.* @AutoService(VariantProcessor::class) class GraphVariantProcessor : VariantProcessor { private val once = Once() - override fun process(variant: BaseVariant) { + override fun process(variant: Variant) { val project = variant.project project.gradle.taskGraph.whenReady { once { @@ -37,7 +32,7 @@ class GraphVariantProcessor : VariantProcessor { } -private fun BaseVariant.generateTaskGraph(): Boolean { +private fun Variant.generateTaskGraph(): Boolean { val taskNames = project.gradle.startParameter.taskNames val dot = project.rootProject.buildDir.file(name, "${taskNames.joinToString("-") { it.replace(":", "") }}.dot") val title = "./gradlew ${taskNames.joinToString(" ")}" @@ -60,7 +55,7 @@ private fun BaseVariant.generateTaskGraph(): Boolean { return true } -private fun BaseVariant.generateProjectGraph() { +private fun Variant.generateProjectGraph() { val rootProject = project.rootProject val graph = Graph.Builder().setTitle(project.toString()) val stack = Stack().apply { diff --git a/booster-task-list-artifact/build.gradle b/booster-task-list-artifact/build.gradle index 0afb3ba9b..23d1e0ebc 100644 --- a/booster-task-list-artifact/build.gradle +++ b/booster-task-list-artifact/build.gradle @@ -4,6 +4,6 @@ dependencies { kapt "com.google.auto.service:auto-service:1.0" implementation 'com.google.auto.service:auto-service:1.0' implementation project(':booster-api') - compileOnly 'com.android.tools.build:gradle:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' + compileOnly 'com.android.tools.build:gradle:8.0.0' + testCompileOnly 'com.android.tools.build:gradle:8.0.0' } diff --git a/booster-task-list-artifact/src/main/kotlin/com/didiglobal/booster/task/artifact/ListArtifact.kt b/booster-task-list-artifact/src/main/kotlin/com/didiglobal/booster/task/artifact/ListArtifact.kt index 942506cf3..23e2821d6 100644 --- a/booster-task-list-artifact/src/main/kotlin/com/didiglobal/booster/task/artifact/ListArtifact.kt +++ b/booster-task-list-artifact/src/main/kotlin/com/didiglobal/booster/task/artifact/ListArtifact.kt @@ -1,6 +1,6 @@ package com.didiglobal.booster.task.artifact -import com.android.build.gradle.api.BaseVariant +import com.android.build.api.variant.Variant import com.didiglobal.booster.gradle.allArtifacts import org.gradle.api.DefaultTask import org.gradle.api.tasks.Internal @@ -10,7 +10,7 @@ import java.io.File internal open class ListArtifact : DefaultTask() { @get:Internal - lateinit var variant: BaseVariant + lateinit var variant: Variant @TaskAction fun run() { diff --git a/booster-task-list-artifact/src/main/kotlin/com/didiglobal/booster/task/artifact/ListArtifactVariantProcessor.kt b/booster-task-list-artifact/src/main/kotlin/com/didiglobal/booster/task/artifact/ListArtifactVariantProcessor.kt index 0c6b946de..12fdc3a42 100644 --- a/booster-task-list-artifact/src/main/kotlin/com/didiglobal/booster/task/artifact/ListArtifactVariantProcessor.kt +++ b/booster-task-list-artifact/src/main/kotlin/com/didiglobal/booster/task/artifact/ListArtifactVariantProcessor.kt @@ -1,9 +1,10 @@ package com.didiglobal.booster.task.artifact -import com.android.build.gradle.api.BaseVariant +import com.android.build.api.variant.Variant import com.android.build.gradle.internal.tasks.factory.dependsOn import com.didiglobal.booster.BOOSTER import com.didiglobal.booster.gradle.project +import com.didiglobal.booster.kotlinx.capitalized import com.didiglobal.booster.task.spi.VariantProcessor import com.google.auto.service.AutoService import org.gradle.api.UnknownTaskException @@ -13,7 +14,7 @@ private const val TASK_NAME = "listArtifacts" @AutoService(VariantProcessor::class) class ListArtifactVariantProcessor : VariantProcessor { - override fun process(variant: BaseVariant) { + override fun process(variant: Variant) { variant.project.tasks.let { tasks -> val listArtifacts = try { tasks.named(TASK_NAME) @@ -23,8 +24,7 @@ class ListArtifactVariantProcessor : VariantProcessor { it.description = "List build artifacts" } } - @Suppress("DEPRECATION") - tasks.register("list${variant.name.capitalize()}Artifacts", ListArtifact::class.java) { + tasks.register("list${variant.name.capitalized()}Artifacts", ListArtifact::class.java) { it.group = BOOSTER it.description = "List build artifacts for ${variant.name}" it.variant = variant diff --git a/booster-task-list-permission/build.gradle b/booster-task-list-permission/build.gradle index 0afb3ba9b..23d1e0ebc 100644 --- a/booster-task-list-permission/build.gradle +++ b/booster-task-list-permission/build.gradle @@ -4,6 +4,6 @@ dependencies { kapt "com.google.auto.service:auto-service:1.0" implementation 'com.google.auto.service:auto-service:1.0' implementation project(':booster-api') - compileOnly 'com.android.tools.build:gradle:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' + compileOnly 'com.android.tools.build:gradle:8.0.0' + testCompileOnly 'com.android.tools.build:gradle:8.0.0' } diff --git a/booster-task-list-permission/src/main/kotlin/com/didiglobal/booster/task/permission/ListPermission.kt b/booster-task-list-permission/src/main/kotlin/com/didiglobal/booster/task/permission/ListPermission.kt index 05298c481..032340a9f 100644 --- a/booster-task-list-permission/src/main/kotlin/com/didiglobal/booster/task/permission/ListPermission.kt +++ b/booster-task-list-permission/src/main/kotlin/com/didiglobal/booster/task/permission/ListPermission.kt @@ -1,27 +1,18 @@ package com.didiglobal.booster.task.permission -import com.android.SdkConstants -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactScope.ALL -import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactType.AAR -import com.android.build.gradle.internal.publishing.AndroidArtifacts.ConsumedConfigType.RUNTIME_CLASSPATH -import com.didiglobal.booster.gradle.getArtifactCollection -import com.didiglobal.booster.kotlinx.CSI_RESET -import com.didiglobal.booster.kotlinx.CSI_YELLOW import com.didiglobal.booster.kotlinx.ifNotEmpty import org.gradle.api.DefaultTask -import org.gradle.api.tasks.Internal +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.tasks.InputFile import org.gradle.api.tasks.TaskAction -import java.io.File -import java.util.zip.ZipFile import javax.xml.parsers.SAXParserFactory -internal open class ListPermission : DefaultTask() { +internal abstract class ListPermission : DefaultTask() { private val factory = SAXParserFactory.newInstance() - @get:Internal - lateinit var variant: BaseVariant + @get:InputFile + abstract val mergedManifest: RegularFileProperty init { factory.isXIncludeAware = false @@ -33,59 +24,15 @@ internal open class ListPermission : DefaultTask() { @TaskAction fun run() { - variant.getArtifactCollection(RUNTIME_CLASSPATH, ALL, AAR).artifactFiles.forEach { aar -> - ZipFile(aar).use { zip -> - zip.getEntry(SdkConstants.FN_ANDROID_MANIFEST_XML)?.let { entry -> - zip.getInputStream(entry).use { source -> - PermissionUsageHandler().also { handler -> - factory.newSAXParser().parse(source, handler) - }.permissions.sorted().ifNotEmpty { permissions -> - println("${aar.componentId} [$$CSI_YELLOW${variant.name}$CSI_RESET]") - permissions.forEach { permission -> - println(" - $permission") - } - } - } + mergedManifest.get().asFile.inputStream().use { source -> + PermissionUsageHandler().also { handler -> + factory.newSAXParser().parse(source, handler) + }.permissions.sorted().ifNotEmpty { permissions -> + permissions.forEach { permission -> + println(" - $permission") } } } } -} - -private val HEX = "[a-zA-Z0-9]+".toRegex() - -private val EXTRA_ANDROID_M2REPOSITORY = "${File.separator}extras${File.separator}android${File.separator}m2repository${File.separator}" -private val LEN_EXTRA_ANDROID_M2REPOSITORY = EXTRA_ANDROID_M2REPOSITORY.length - -private val EXTRA_GOOGLE_M2REPOSITORY = "${File.separator}extras${File.separator}google${File.separator}m2repository${File.separator}" -private val LEN_EXTRA_GOOGLE_M2REPOSITORY = EXTRA_GOOGLE_M2REPOSITORY.length - -internal val File.componentId: String - get() { - val parent = this.parentFile - if (parent.name.matches(HEX)) { - val version = parent.parentFile - val artifact = version.parentFile - val group = artifact.parentFile - return "${group.name}:${artifact.name}:${version.name}" - } - - this.canonicalPath.let { - val idxAndroidM2 = it.indexOf(EXTRA_ANDROID_M2REPOSITORY) - if (idxAndroidM2 > -1) { - val artifact = parent.parentFile - val group = artifact.parentFile.canonicalPath.substring(idxAndroidM2 + LEN_EXTRA_ANDROID_M2REPOSITORY).replace(File.separatorChar, '.') - return "$group:${artifact.name}:${parent.name}" - } - - val idxGoogleM2 = it.indexOf(EXTRA_GOOGLE_M2REPOSITORY) - if (idxGoogleM2 > -1) { - val artifact = parent.parentFile - val group = artifact.parentFile.canonicalPath.substring(idxGoogleM2 + LEN_EXTRA_GOOGLE_M2REPOSITORY).replace(File.separatorChar, '.') - return "$group:${artifact.name}:${parent.name}" - } - - TODO("Unrecognizable AAR: $canonicalPath") - } - } +} \ No newline at end of file diff --git a/booster-task-list-permission/src/main/kotlin/com/didiglobal/booster/task/permission/ListPermissionVariantProcessor.kt b/booster-task-list-permission/src/main/kotlin/com/didiglobal/booster/task/permission/ListPermissionVariantProcessor.kt index eab14946b..88bb86906 100644 --- a/booster-task-list-permission/src/main/kotlin/com/didiglobal/booster/task/permission/ListPermissionVariantProcessor.kt +++ b/booster-task-list-permission/src/main/kotlin/com/didiglobal/booster/task/permission/ListPermissionVariantProcessor.kt @@ -1,9 +1,11 @@ package com.didiglobal.booster.task.permission -import com.android.build.gradle.api.BaseVariant +import com.android.build.api.artifact.SingleArtifact +import com.android.build.api.variant.Variant import com.android.build.gradle.internal.tasks.factory.dependsOn import com.didiglobal.booster.BOOSTER import com.didiglobal.booster.gradle.project +import com.didiglobal.booster.kotlinx.capitalized import com.didiglobal.booster.task.spi.VariantProcessor import com.google.auto.service.AutoService import org.gradle.api.UnknownTaskException @@ -13,7 +15,7 @@ private const val TASK_NAME = "listPermissions" @AutoService(VariantProcessor::class) class ListPermissionVariantProcessor : VariantProcessor { - override fun process(variant: BaseVariant) { + override fun process(variant: Variant) { variant.project.tasks.let { tasks -> val listPermissions = try { tasks.named(TASK_NAME) @@ -23,12 +25,11 @@ class ListPermissionVariantProcessor : VariantProcessor { it.description = "List the permissions declared in AndroidManifest.xml" } } - @Suppress("DEPRECATION") - tasks.register("list${variant.name.capitalize()}Permissions", ListPermission::class.java) { + tasks.register("list${variant.name.capitalized()}Permissions", ListPermission::class.java) { it.group = BOOSTER it.description = "List the permission declared in AndroidManifest.xml for ${variant.name}" - it.variant = variant it.outputs.upToDateWhen { false } + it.mergedManifest.set(variant.artifacts.get(SingleArtifact.MERGED_MANIFEST)) }.also { listPermissions.dependsOn(it) } diff --git a/booster-task-list-shared-library/build.gradle b/booster-task-list-shared-library/build.gradle index 0afb3ba9b..23d1e0ebc 100644 --- a/booster-task-list-shared-library/build.gradle +++ b/booster-task-list-shared-library/build.gradle @@ -4,6 +4,6 @@ dependencies { kapt "com.google.auto.service:auto-service:1.0" implementation 'com.google.auto.service:auto-service:1.0' implementation project(':booster-api') - compileOnly 'com.android.tools.build:gradle:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' + compileOnly 'com.android.tools.build:gradle:8.0.0' + testCompileOnly 'com.android.tools.build:gradle:8.0.0' } diff --git a/booster-task-list-shared-library/src/main/kotlin/com/didiglobal/booster/task/so/ListSharedLibrary.kt b/booster-task-list-shared-library/src/main/kotlin/com/didiglobal/booster/task/so/ListSharedLibrary.kt index acd19a1d9..51823a5bd 100644 --- a/booster-task-list-shared-library/src/main/kotlin/com/didiglobal/booster/task/so/ListSharedLibrary.kt +++ b/booster-task-list-shared-library/src/main/kotlin/com/didiglobal/booster/task/so/ListSharedLibrary.kt @@ -1,6 +1,6 @@ package com.didiglobal.booster.task.so -import com.android.build.gradle.api.BaseVariant +import com.android.build.api.variant.Variant import com.didiglobal.booster.gradle.dependencies import com.didiglobal.booster.kotlinx.CSI_CYAN import com.didiglobal.booster.kotlinx.CSI_RESET @@ -13,7 +13,7 @@ import java.util.jar.JarFile internal open class ListSharedLibrary : DefaultTask() { @get:Internal - lateinit var variant: BaseVariant + lateinit var variant: Variant @TaskAction fun run() { diff --git a/booster-task-list-shared-library/src/main/kotlin/com/didiglobal/booster/task/so/ListSharedLibraryVariantProcessor.kt b/booster-task-list-shared-library/src/main/kotlin/com/didiglobal/booster/task/so/ListSharedLibraryVariantProcessor.kt index 3d3504851..a92dfa709 100644 --- a/booster-task-list-shared-library/src/main/kotlin/com/didiglobal/booster/task/so/ListSharedLibraryVariantProcessor.kt +++ b/booster-task-list-shared-library/src/main/kotlin/com/didiglobal/booster/task/so/ListSharedLibraryVariantProcessor.kt @@ -1,9 +1,10 @@ package com.didiglobal.booster.task.so -import com.android.build.gradle.api.BaseVariant +import com.android.build.api.variant.Variant import com.android.build.gradle.internal.tasks.factory.dependsOn import com.didiglobal.booster.BOOSTER import com.didiglobal.booster.gradle.project +import com.didiglobal.booster.kotlinx.capitalized import com.didiglobal.booster.task.spi.VariantProcessor import com.google.auto.service.AutoService import org.gradle.api.UnknownTaskException @@ -13,7 +14,7 @@ private const val TASK_NAME = "listSharedLibraries" @AutoService(VariantProcessor::class) class ListSharedLibraryVariantProcessor : VariantProcessor { - override fun process(variant: BaseVariant) { + override fun process(variant: Variant) { variant.project.tasks.let { tasks -> val listSharedLibraries = try { tasks.named(TASK_NAME) @@ -23,8 +24,7 @@ class ListSharedLibraryVariantProcessor : VariantProcessor { it.description = "List the shared libraries that current project depends on" } } - @Suppress("DEPRECATION") - tasks.register("list${variant.name.capitalize()}SharedLibraries", ListSharedLibrary::class.java) { + tasks.register("list${variant.name.capitalized()}SharedLibraries", ListSharedLibrary::class.java) { it.group = BOOSTER it.description = "List the shared libraries that current project depends on for ${variant.name}" it.outputs.upToDateWhen { false } diff --git a/booster-task-resource-deredundancy/README.md b/booster-task-resource-deredundancy/README.md deleted file mode 100644 index 731387a9d..000000000 --- a/booster-task-resource-deredundancy/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# booster-task-resource-deredundancy - diff --git a/booster-task-resource-deredundancy/build.gradle b/booster-task-resource-deredundancy/build.gradle deleted file mode 100644 index 42eaccc1b..000000000 --- a/booster-task-resource-deredundancy/build.gradle +++ /dev/null @@ -1,10 +0,0 @@ -apply from: "$rootDir/gradle/booster.gradle" - -dependencies { - kapt "com.google.auto.service:auto-service:1.0" - implementation project(':booster-task-compression') - compileOnly 'com.android.tools.build:gradle:4.0.0' - compileOnly 'com.android.tools.build:builder:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' - testCompileOnly 'com.android.tools.build:builder:4.0.0' -} diff --git a/booster-task-resource-deredundancy/src/main/kotlin/com/didiglobal/booster/task/resource/deredundancy/LayoutDirHandler.kt b/booster-task-resource-deredundancy/src/main/kotlin/com/didiglobal/booster/task/resource/deredundancy/LayoutDirHandler.kt deleted file mode 100644 index a8c30acae..000000000 --- a/booster-task-resource-deredundancy/src/main/kotlin/com/didiglobal/booster/task/resource/deredundancy/LayoutDirHandler.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.didiglobal.booster.task.resource.deredundancy - -import org.xml.sax.Attributes -import org.xml.sax.helpers.DefaultHandler - -internal class LayoutDirHandler : DefaultHandler() { - - var supportsRtl = false - - override fun startElement(uri: String, localName: String, qName: String, attributes: Attributes) { - if ("application" == qName) { - this.supportsRtl = attributes.getValue("android:supportsRtl")?.toBoolean() ?: false - } - } - -} diff --git a/booster-task-resource-deredundancy/src/main/kotlin/com/didiglobal/booster/task/resource/deredundancy/RemoveRedundantFlatImages.kt b/booster-task-resource-deredundancy/src/main/kotlin/com/didiglobal/booster/task/resource/deredundancy/RemoveRedundantFlatImages.kt deleted file mode 100644 index 161f01526..000000000 --- a/booster-task-resource-deredundancy/src/main/kotlin/com/didiglobal/booster/task/resource/deredundancy/RemoveRedundantFlatImages.kt +++ /dev/null @@ -1,81 +0,0 @@ -package com.didiglobal.booster.task.resource.deredundancy - -import com.didiglobal.booster.aapt.Configuration -import com.didiglobal.booster.aapt2.Aapt2Container -import com.didiglobal.booster.aapt2.metadata -import com.didiglobal.booster.compression.CompressionResult -import com.didiglobal.booster.compression.isFlatPng -import com.didiglobal.booster.compression.isPng -import com.didiglobal.booster.gradle.isAapt2Enabled -import com.didiglobal.booster.gradle.mergedRes -import com.didiglobal.booster.kotlinx.search -import org.gradle.api.tasks.TaskAction -import java.io.File -import java.io.IOException -import java.util.stream.Collectors - -/** - * Represents a task for redundant resources reducing - * - * @author johnsonlee - */ -internal open class RemoveRedundantFlatImages : RemoveRedundantImages() { - - @TaskAction - override fun run() { - val resources = variant.mergedRes.search(if (project.isAapt2Enabled) ::isFlatPng else ::isPng).parallelStream().map { - it to it.metadata - }.collect(Collectors.toSet()) - - resources.filter { - when { - variant.isSupportsRtl -> true - // remove ldrtl resources if RTL is not supported - it.second.configuration.screenConfig.layout == Configuration.ScreenConfig.SCREEN_LAYOUT_DIR_RTL -> { - it.remove() - false - } - else -> true - } - }.groupBy({ - it.second.resourceName.substringBeforeLast('/') // group by resource type, eg. drawable, mipmap, etc. - }, { - it.first to it.second - }).forEach { entry -> // resource type => resources - entry.value.groupBy({ - // resource name with configuration except density - Configuration(it.second.configuration).apply { - screenType.density = Configuration.ScreenType.DENSITY_DEFAULT - }.toString(it.second.resourceName.substringAfterLast('/')) - }, { - it.first to it.second - }).map { group -> // resource name with configuration => resources - // calculate the maximum density of the resource group with same name - val highest = group.value.maxByOrNull { - it.second.configuration.screenType.density - }?.second?.configuration?.screenType?.density - - // select the grouped resources except the one with maximum density - group.value.filter { - it.second.configuration.screenType.density != highest - } - }.flatten().parallelStream().forEach { - it.remove() - } - } - } - - private fun Pair.remove() { - try { - if (this.first.delete()) { - val original = File(this.second.sourcePath) - results.add(CompressionResult(this.first, original.length(), 0, original)) - } else { - logger.error("Cannot delete file `${this.first}`") - } - } catch (e: IOException) { - logger.error("Cannot delete file `${this.first}`", e) - } - } - -} diff --git a/booster-task-resource-deredundancy/src/main/kotlin/com/didiglobal/booster/task/resource/deredundancy/RemoveRedundantImages.kt b/booster-task-resource-deredundancy/src/main/kotlin/com/didiglobal/booster/task/resource/deredundancy/RemoveRedundantImages.kt deleted file mode 100644 index f95f048a9..000000000 --- a/booster-task-resource-deredundancy/src/main/kotlin/com/didiglobal/booster/task/resource/deredundancy/RemoveRedundantImages.kt +++ /dev/null @@ -1,46 +0,0 @@ -package com.didiglobal.booster.task.resource.deredundancy - -import com.android.SdkConstants -import com.android.build.gradle.api.BaseVariant -import com.didiglobal.booster.compression.CompressionResults -import com.didiglobal.booster.gradle.mergedManifests -import com.didiglobal.booster.kotlinx.search -import org.gradle.api.DefaultTask -import org.gradle.api.tasks.Internal -import org.gradle.api.tasks.TaskAction -import javax.xml.parsers.SAXParserFactory - -/** - * Represents a task for redundant resources reducing - */ -internal open class RemoveRedundantImages : DefaultTask() { - - @get:Internal - lateinit var variant: BaseVariant - - @get:Internal - lateinit var results: CompressionResults - - @TaskAction - open fun run() { - TODO("Reducing redundant resources without aapt2 enabled has not supported yet") - } - -} - -internal val BaseVariant.isSupportsRtl: Boolean - get() { - val parser = SAXParserFactory.newInstance().newSAXParser() - return mergedManifests.search { - it.name == SdkConstants.ANDROID_MANIFEST_XML - }.parallelStream().map { manifest -> - LayoutDirHandler().let { - parser.parse(manifest, it) - it.supportsRtl - } - }.toArray { size -> - arrayOfNulls(size) - }.fold(true) { acc, i -> - acc and i - } - } \ No newline at end of file diff --git a/booster-task-resource-deredundancy/src/main/kotlin/com/didiglobal/booster/task/resource/deredundancy/ResourceDeredundancyVariantProcessor.kt b/booster-task-resource-deredundancy/src/main/kotlin/com/didiglobal/booster/task/resource/deredundancy/ResourceDeredundancyVariantProcessor.kt deleted file mode 100644 index 817b9e511..000000000 --- a/booster-task-resource-deredundancy/src/main/kotlin/com/didiglobal/booster/task/resource/deredundancy/ResourceDeredundancyVariantProcessor.kt +++ /dev/null @@ -1,62 +0,0 @@ -package com.didiglobal.booster.task.resource.deredundancy - -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.internal.tasks.factory.dependsOn -import com.didiglobal.booster.BOOSTER -import com.didiglobal.booster.annotations.Priority -import com.didiglobal.booster.compression.CompressionResults -import com.didiglobal.booster.compression.generateReport -import com.didiglobal.booster.compression.task.CompressImages -import com.didiglobal.booster.gradle.getTaskName -import com.didiglobal.booster.gradle.isAapt2Enabled -import com.didiglobal.booster.gradle.mergeResourcesTaskProvider -import com.didiglobal.booster.gradle.project -import com.didiglobal.booster.task.spi.VariantProcessor -import com.google.auto.service.AutoService -import org.gradle.api.UnknownTaskException - - -/** - * Represents a variant processor for resource deredundancy - * - * @author johnsonlee - */ -@Priority(-1) -@AutoService(VariantProcessor::class) -class ResourceDeredundancyVariantProcessor : VariantProcessor { - - override fun process(variant: BaseVariant) { - val project = variant.project - val results = CompressionResults() - val klassRemoveRedundantImages = if (project.isAapt2Enabled) RemoveRedundantFlatImages::class else RemoveRedundantImages::class - @Suppress("DEPRECATION") - val deredundancy = variant.project.tasks.register("remove${variant.name.capitalize()}RedundantResources", klassRemoveRedundantImages.java) { task -> - task.group = BOOSTER - task.description = "Remove redundant resources for ${variant.name}" - task.outputs.upToDateWhen { false } - task.variant = variant - task.results = results - }.apply { - (try { - project.tasks.named(variant.getTaskName("process", "Manifest")) - } catch (e: UnknownTaskException) { - null - })?.let { - dependsOn(it) - } - dependsOn(variant.mergeResourcesTaskProvider) - configure { - it.doLast { - results.generateReport(variant, Build.ARTIFACT) - } - } - } - - variant.project.tasks.withType(CompressImages::class.java).filter { - it.variant.name == variant.name - }.forEach { - it.dependsOn(deredundancy) - } - } - -} diff --git a/booster-task-spi/build.gradle b/booster-task-spi/build.gradle index 84ffa5ec0..a698a040c 100644 --- a/booster-task-spi/build.gradle +++ b/booster-task-spi/build.gradle @@ -1,6 +1,7 @@ apply from: "$rootDir/gradle/booster.gradle" dependencies { - compileOnly 'com.android.tools.build:gradle:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' + implementation gradleApi() + compileOnly 'com.android.tools.build:gradle:8.0.0' + testCompileOnly 'com.android.tools.build:gradle:8.0.0' } diff --git a/booster-task-spi/src/main/kotlin/com/didiglobal/booster/task/spi/VariantProcessor.kt b/booster-task-spi/src/main/kotlin/com/didiglobal/booster/task/spi/VariantProcessor.kt index c120853e4..ad121caa0 100644 --- a/booster-task-spi/src/main/kotlin/com/didiglobal/booster/task/spi/VariantProcessor.kt +++ b/booster-task-spi/src/main/kotlin/com/didiglobal/booster/task/spi/VariantProcessor.kt @@ -1,9 +1,21 @@ package com.didiglobal.booster.task.spi +import com.android.build.api.variant.Variant +import com.android.build.api.variant.VariantBuilder import com.android.build.gradle.api.BaseVariant interface VariantProcessor { - fun process(variant: BaseVariant) + @Deprecated( + message = "BaseVariant is deprecated, please use process(variant: Variant) method instead", + replaceWith = ReplaceWith( + expression = "process(variant: Variant)" + ) + ) + fun process(variant: BaseVariant) = Unit + + fun beforeProcess(variantBuilder: VariantBuilder) = Unit + + fun process(variant: Variant) = Unit } diff --git a/booster-transform-activity-thread/build.gradle b/booster-transform-activity-thread/build.gradle index 463c7385e..f0bf91bf4 100644 --- a/booster-transform-activity-thread/build.gradle +++ b/booster-transform-activity-thread/build.gradle @@ -4,6 +4,6 @@ dependencies { kapt "com.google.auto.service:auto-service:1.0" implementation project(':booster-api') implementation project(':booster-transform-asm') - compileOnly 'com.android.tools.build:gradle:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' + compileOnly 'com.android.tools.build:gradle:8.0.0' + testCompileOnly 'com.android.tools.build:gradle:8.0.0' } diff --git a/booster-transform-activity-thread/src/main/kotlin/com/didiglobal/booster/transform/activitythread/ActivityThreadVariantProcessor.kt b/booster-transform-activity-thread/src/main/kotlin/com/didiglobal/booster/transform/activitythread/ActivityThreadVariantProcessor.kt new file mode 100644 index 000000000..2454ac28a --- /dev/null +++ b/booster-transform-activity-thread/src/main/kotlin/com/didiglobal/booster/transform/activitythread/ActivityThreadVariantProcessor.kt @@ -0,0 +1,26 @@ +package com.didiglobal.booster.transform.activitythread + +import com.android.build.api.variant.DynamicFeatureVariantBuilder +import com.android.build.api.variant.LibraryVariantBuilder +import com.android.build.api.variant.VariantBuilder +import com.didiglobal.booster.gradle.* +import com.didiglobal.booster.task.spi.VariantProcessor +import com.didiglobal.booster.transform.activity.thread.Build.GROUP +import com.didiglobal.booster.transform.activity.thread.Build.VERSION +import com.google.auto.service.AutoService +import org.gradle.api.Project + +/** + * @author neighbWang + */ +@AutoService(VariantProcessor::class) +class ActivityThreadVariantProcessor(private val project: Project) : VariantProcessor { + + override fun beforeProcess(variantBuilder: VariantBuilder) { + if (variantBuilder is LibraryVariantBuilder || variantBuilder is DynamicFeatureVariantBuilder) { + return + } + project.dependencies.add("${variantBuilder.name}Implementation", "$GROUP:booster-android-instrument-activity-thread:$VERSION") + } + +} diff --git a/booster-transform-activity-thread/src/main/kotlin/com/didiglobal/booster/transform/activitythread/ActivityThreadVarinatProcessor.kt b/booster-transform-activity-thread/src/main/kotlin/com/didiglobal/booster/transform/activitythread/ActivityThreadVarinatProcessor.kt deleted file mode 100644 index 907be99b6..000000000 --- a/booster-transform-activity-thread/src/main/kotlin/com/didiglobal/booster/transform/activitythread/ActivityThreadVarinatProcessor.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.didiglobal.booster.transform.activitythread - -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.LibraryVariant -import com.didiglobal.booster.gradle.isDynamicFeature -import com.didiglobal.booster.gradle.project -import com.didiglobal.booster.task.spi.VariantProcessor -import com.didiglobal.booster.transform.activity.thread.Build -import com.google.auto.service.AutoService - -/** - * @author neighbWang - */ -@AutoService(VariantProcessor::class) -class ActivityThreadVarinatProcessor : VariantProcessor { - - override fun process(variant: BaseVariant) { - if (variant !is LibraryVariant && !variant.isDynamicFeature) { - variant.project.dependencies.add("implementation", "${Build.GROUP}:booster-android-instrument-activity-thread:${Build.VERSION}") - } - } - -} diff --git a/booster-transform-asm/build.gradle b/booster-transform-asm/build.gradle index 2d86165d2..df7cd8a41 100644 --- a/booster-transform-asm/build.gradle +++ b/booster-transform-asm/build.gradle @@ -5,10 +5,10 @@ dependencies { kaptTest 'com.google.auto.service:auto-service:1.0' api project(':booster-annotations') api project(':booster-transform-util') - api 'org.ow2.asm:asm:7.1' - api 'org.ow2.asm:asm-analysis:7.1' - api 'org.ow2.asm:asm-commons:7.1' - api 'org.ow2.asm:asm-tree:7.1' - api 'org.ow2.asm:asm-util:7.1' + api 'org.ow2.asm:asm:9.1' + api 'org.ow2.asm:asm-analysis:9.2' + api 'org.ow2.asm:asm-commons:9.2' + api 'org.ow2.asm:asm-tree:9.2' + api 'org.ow2.asm:asm-util:9.2' api 'com.google.auto.service:auto-service:1.0' } diff --git a/booster-transform-br-inline/README.md b/booster-transform-br-inline/README.md deleted file mode 100644 index 53f276b59..000000000 --- a/booster-transform-br-inline/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# booster-transform-br-inline - -This module is used for BR index inline if databinding is enabled. - diff --git a/booster-transform-br-inline/build.gradle b/booster-transform-br-inline/build.gradle deleted file mode 100644 index 65ef172f3..000000000 --- a/booster-transform-br-inline/build.gradle +++ /dev/null @@ -1,8 +0,0 @@ -apply from: "$rootDir/gradle/booster.gradle" - -dependencies { - kapt "com.google.auto.service:auto-service:1.0" - implementation project(':booster-aapt2') - implementation project(':booster-api') - implementation project(':booster-transform-asm') -} diff --git a/booster-transform-br-inline/src/main/kotlin/com/didiglobal/booster/transform/br/inline/BRInlineTransformer.kt b/booster-transform-br-inline/src/main/kotlin/com/didiglobal/booster/transform/br/inline/BRInlineTransformer.kt deleted file mode 100644 index de06874e1..000000000 --- a/booster-transform-br-inline/src/main/kotlin/com/didiglobal/booster/transform/br/inline/BRInlineTransformer.kt +++ /dev/null @@ -1,130 +0,0 @@ -package com.didiglobal.booster.transform.br.inline - -import com.didiglobal.booster.kotlinx.asIterable -import com.didiglobal.booster.kotlinx.search -import com.didiglobal.booster.kotlinx.touch -import com.didiglobal.booster.transform.ArtifactManager.Companion.ALL_CLASSES -import com.didiglobal.booster.transform.ArtifactManager.Companion.DATA_BINDING_DEPENDENCY_ARTIFACTS -import com.didiglobal.booster.transform.TransformContext -import com.didiglobal.booster.transform.asm.ClassTransformer -import com.google.auto.service.AutoService -import org.gradle.api.logging.Logging -import org.objectweb.asm.Opcodes.GETSTATIC -import org.objectweb.asm.tree.ClassNode -import org.objectweb.asm.tree.FieldInsnNode -import org.objectweb.asm.tree.LdcInsnNode -import java.io.File -import java.io.PrintWriter - -internal const val BR_FILE_EXT = "-br.bin" - -/** - * Represents a class node transformer for constants shrinking - * - * @author linjiang - */ -@AutoService(ClassTransformer::class) -class BRInlineTransformer : ClassTransformer { - - private lateinit var symbols: SymbolList - private lateinit var logger: PrintWriter - private lateinit var validClasses: Set - - override val name: String = Build.ARTIFACT - - override fun onPreTransform(context: TransformContext) { - logger = getReport(context, "report.txt").touch().printWriter() - validClasses = context.findValidClasses() - val allBR = context.findAllBR() - symbols = allBR.find { it.second == context.appBR }?.first?.let { - SymbolList.from(it) - } ?: SymbolList.Builder().build() - if (symbols.isEmpty()) { - "Inline BR symbols failed: BR.class doesn't exist or blank".apply { - logger_.error(this) - logger.println(this) - } - return - } - // Remove all BR class files - allBR.also { pairs -> - val totalSize = allBR.sumOf { it.first.length() } - val maxWidth = allBR.maxOfOrNull { it.second.length }?.plus(10) ?: 10 - - logger.println("Delete files:") - - pairs.forEach { - if (it.first.delete()) { - logger.println(" - `${it.second}`") - } - } - - logger.println("-".repeat(maxWidth)) - logger.println("Total: $totalSize bytes") - logger.println() - } - } - - override fun transform(context: TransformContext, klass: ClassNode): ClassNode { - if (symbols.isEmpty()) { - return klass - } - klass.replaceSymbolReferenceWithConstant() - return klass - } - - override fun onPostTransform(context: TransformContext) { - this.logger.close() - } - - private val TransformContext.appBR - get() = "${originalApplicationId.replace('.', '/')}/BR.class" - - private fun TransformContext.findValidClasses(): Set { - return if (isDataBindingEnabled) { - artifacts.get(DATA_BINDING_DEPENDENCY_ARTIFACTS) - .filter { it.name.endsWith(BR_FILE_EXT) } - .map { "${it.name.substringBefore("-").replace('.', '/')}/BR.class" } - .plus(appBR) - .toSet() - } else { - emptySet() - } - } - - private fun TransformContext.findAllBR(): List> { - return artifacts.get(ALL_CLASSES).map { classes -> - val base = classes.toURI() - classes.search { r -> - base.relativize(r.toURI()).path in validClasses - }.map { r -> - r to base.relativize(r.toURI()).path - } - }.flatten() - } - - private fun ClassNode.replaceSymbolReferenceWithConstant() { - methods.forEach { method -> - method.instructions.iterator().asIterable().filter { - it.opcode == GETSTATIC - }.map { - it as FieldInsnNode - }.filter { - "I" == it.desc && "${it.owner}.class" in validClasses - }.forEach { field -> - // Replace int field with constant - try { - method.instructions.insertBefore(field, LdcInsnNode(symbols.getInt(field.name))) - method.instructions.remove(field) - logger.println(" * ${field.owner}.${field.name} => ${symbols.getInt(field.name)}: ${name}.${method.name}${method.desc}") - } catch (e: NullPointerException) { - logger.println(" ! Unresolvable symbol `${field.owner}.${field.name}` : $name.${method.name}${method.desc}") - } - } - } - } - -} - - -private val logger_ = Logging.getLogger(BRInlineTransformer::class.java) diff --git a/booster-transform-br-inline/src/main/kotlin/com/didiglobal/booster/transform/br/inline/SymbolList.kt b/booster-transform-br-inline/src/main/kotlin/com/didiglobal/booster/transform/br/inline/SymbolList.kt deleted file mode 100644 index acf31b527..000000000 --- a/booster-transform-br-inline/src/main/kotlin/com/didiglobal/booster/transform/br/inline/SymbolList.kt +++ /dev/null @@ -1,63 +0,0 @@ -package com.didiglobal.booster.transform.br.inline - -import org.objectweb.asm.ClassReader -import org.objectweb.asm.tree.ClassNode -import java.io.File - -/** - * Represents the symbol list of BR - * - * @author linjiang - */ -class SymbolList private constructor(builder: Builder) : Iterable { - - private val symbols = builder.symbols - - override fun iterator(): Iterator = this.symbols.iterator() - - fun getInt(name: String): Int { - return this.symbols.find { it.name == name }?.value!! - } - - fun isEmpty() = this.symbols.isEmpty() - - data class Symbol(val name: String, val value: Int) - - - class Builder { - - val symbols = mutableListOf() - - fun build(): SymbolList { - return SymbolList(this) - } - - fun addSymbol(symbol: Symbol): Builder { - this.symbols.add(symbol) - return this - } - - } - - companion object { - - /** - * Parses symbols from the specified file - * - * @param file symbol list file - */ - fun from(file: File) = Builder().also { builder -> - if (file.exists()) { - ClassNode().also { - ClassReader(file.inputStream()).accept(it, 0) - }.fields.forEach { - if (it.value is Int) { - builder.addSymbol(Symbol(it.name, it.value as Int)) - } - } - } - }.build() - - } - -} diff --git a/booster-transform-br-inline/src/test/kotlin/com/didiglobal/booster/transform/br/inline/SymbolListTest.kt b/booster-transform-br-inline/src/test/kotlin/com/didiglobal/booster/transform/br/inline/SymbolListTest.kt deleted file mode 100644 index 27cd09004..000000000 --- a/booster-transform-br-inline/src/test/kotlin/com/didiglobal/booster/transform/br/inline/SymbolListTest.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.didiglobal.booster.transform.br.inline - -import com.didiglobal.booster.kotlinx.file -import java.io.File -import kotlin.test.Test - -val PWD = File(System.getProperty("user.dir")) - -class SymbolListTest { - - @Test - fun `parse symbol list from BR class`() { - SymbolList.from(PWD.file("src", "test", "resources", "BR.class")).forEach { symbol -> - println(symbol) - } - } - -} diff --git a/booster-transform-br-inline/src/test/resources/BR.class b/booster-transform-br-inline/src/test/resources/BR.class deleted file mode 100644 index 41dde1057..000000000 Binary files a/booster-transform-br-inline/src/test/resources/BR.class and /dev/null differ diff --git a/booster-transform-finalizer-watchdog-daemon/build.gradle b/booster-transform-finalizer-watchdog-daemon/build.gradle index 463c7385e..f0bf91bf4 100644 --- a/booster-transform-finalizer-watchdog-daemon/build.gradle +++ b/booster-transform-finalizer-watchdog-daemon/build.gradle @@ -4,6 +4,6 @@ dependencies { kapt "com.google.auto.service:auto-service:1.0" implementation project(':booster-api') implementation project(':booster-transform-asm') - compileOnly 'com.android.tools.build:gradle:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' + compileOnly 'com.android.tools.build:gradle:8.0.0' + testCompileOnly 'com.android.tools.build:gradle:8.0.0' } diff --git a/booster-transform-finalizer-watchdog-daemon/src/main/kotlin/com/didiglobal/booster/transform/finalizer/watchdog/daemon/FinalizerWatchdogDaemonTransformer.kt b/booster-transform-finalizer-watchdog-daemon/src/main/kotlin/com/didiglobal/booster/transform/finalizer/watchdog/daemon/FinalizerWatchdogDaemonTransformer.kt index 21fdf9bb9..13c190935 100644 --- a/booster-transform-finalizer-watchdog-daemon/src/main/kotlin/com/didiglobal/booster/transform/finalizer/watchdog/daemon/FinalizerWatchdogDaemonTransformer.kt +++ b/booster-transform-finalizer-watchdog-daemon/src/main/kotlin/com/didiglobal/booster/transform/finalizer/watchdog/daemon/FinalizerWatchdogDaemonTransformer.kt @@ -6,6 +6,7 @@ import com.didiglobal.booster.transform.TransformContext import com.didiglobal.booster.transform.asm.ClassTransformer import com.didiglobal.booster.transform.asm.className import com.didiglobal.booster.transform.asm.findAll +import com.didiglobal.booster.transform.finalizer.watchdog.daemon.Build.ARTIFACT import com.didiglobal.booster.transform.util.ComponentHandler import com.google.auto.service.AutoService import org.objectweb.asm.Opcodes @@ -33,7 +34,7 @@ class FinalizerWatchdogDaemonTransformer : ClassTransformer { private lateinit var logger: PrintWriter private val applications = mutableSetOf() - override val name: String = Build.ARTIFACT + override val name: String = ARTIFACT override fun onPreTransform(context: TransformContext) { val parser = SAXParserFactory.newInstance().newSAXParser() diff --git a/booster-transform-finalizer-watchdog-daemon/src/main/kotlin/com/didiglobal/booster/transform/finalizer/watchdog/daemon/FinalizerWatchdogDaemonVariantProcessor.kt b/booster-transform-finalizer-watchdog-daemon/src/main/kotlin/com/didiglobal/booster/transform/finalizer/watchdog/daemon/FinalizerWatchdogDaemonVariantProcessor.kt index 961f9fb1e..9b23eebee 100644 --- a/booster-transform-finalizer-watchdog-daemon/src/main/kotlin/com/didiglobal/booster/transform/finalizer/watchdog/daemon/FinalizerWatchdogDaemonVariantProcessor.kt +++ b/booster-transform-finalizer-watchdog-daemon/src/main/kotlin/com/didiglobal/booster/transform/finalizer/watchdog/daemon/FinalizerWatchdogDaemonVariantProcessor.kt @@ -1,22 +1,26 @@ package com.didiglobal.booster.transform.finalizer.watchdog.daemon -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.LibraryVariant -import com.didiglobal.booster.gradle.isDynamicFeature -import com.didiglobal.booster.gradle.project +import com.android.build.api.variant.DynamicFeatureVariantBuilder +import com.android.build.api.variant.LibraryVariantBuilder +import com.android.build.api.variant.VariantBuilder import com.didiglobal.booster.task.spi.VariantProcessor +import com.didiglobal.booster.transform.finalizer.watchdog.daemon.Build.GROUP +import com.didiglobal.booster.transform.finalizer.watchdog.daemon.Build.VERSION import com.google.auto.service.AutoService +import org.gradle.api.Project /** * @author neighbWang */ @AutoService(VariantProcessor::class) -class FinalizerWatchdogDaemonVariantProcessor : VariantProcessor { +class FinalizerWatchdogDaemonVariantProcessor(private val project: Project) : VariantProcessor { - override fun process(variant: BaseVariant) { - if (variant !is LibraryVariant && !variant.isDynamicFeature) { - variant.project.dependencies.add("implementation", "${Build.GROUP}:booster-android-instrument-finalizer-watchdog-daemon:${Build.VERSION}") + override fun beforeProcess(variantBuilder: VariantBuilder) { + if (variantBuilder is LibraryVariantBuilder || variantBuilder is DynamicFeatureVariantBuilder) { + return } + project.dependencies.add("${variantBuilder.name}Implementation", "$GROUP:booster-android-instrument-finalizer-watchdog-daemon:$VERSION") + } } diff --git a/booster-transform-logcat/build.gradle b/booster-transform-logcat/build.gradle index 463c7385e..f0bf91bf4 100644 --- a/booster-transform-logcat/build.gradle +++ b/booster-transform-logcat/build.gradle @@ -4,6 +4,6 @@ dependencies { kapt "com.google.auto.service:auto-service:1.0" implementation project(':booster-api') implementation project(':booster-transform-asm') - compileOnly 'com.android.tools.build:gradle:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' + compileOnly 'com.android.tools.build:gradle:8.0.0' + testCompileOnly 'com.android.tools.build:gradle:8.0.0' } diff --git a/booster-transform-logcat/src/main/kotlin/com/didiglobal/booster/transform/logcat/LogcatTransformer.kt b/booster-transform-logcat/src/main/kotlin/com/didiglobal/booster/transform/logcat/LogcatTransformer.kt index 45d71e714..f647ba9fe 100644 --- a/booster-transform-logcat/src/main/kotlin/com/didiglobal/booster/transform/logcat/LogcatTransformer.kt +++ b/booster-transform-logcat/src/main/kotlin/com/didiglobal/booster/transform/logcat/LogcatTransformer.kt @@ -4,6 +4,7 @@ import com.didiglobal.booster.kotlinx.asIterable import com.didiglobal.booster.kotlinx.touch import com.didiglobal.booster.transform.TransformContext import com.didiglobal.booster.transform.asm.ClassTransformer +import com.didiglobal.booster.transform.logcat.Build.* import com.google.auto.service.AutoService import org.objectweb.asm.Opcodes.GETSTATIC import org.objectweb.asm.Opcodes.INVOKESTATIC @@ -30,7 +31,7 @@ class LogcatTransformer : ClassTransformer { private lateinit var logger: PrintWriter - override val name: String = Build.ARTIFACT + override val name: String = ARTIFACT override fun onPreTransform(context: TransformContext) { this.logger = getReport(context, "report.txt").touch().printWriter() diff --git a/booster-transform-logcat/src/main/kotlin/com/didiglobal/booster/transform/logcat/LogcatVariantProcessor.kt b/booster-transform-logcat/src/main/kotlin/com/didiglobal/booster/transform/logcat/LogcatVariantProcessor.kt new file mode 100644 index 000000000..c7343fc15 --- /dev/null +++ b/booster-transform-logcat/src/main/kotlin/com/didiglobal/booster/transform/logcat/LogcatVariantProcessor.kt @@ -0,0 +1,25 @@ +package com.didiglobal.booster.transform.logcat + +import com.android.build.api.variant.DynamicFeatureVariantBuilder +import com.android.build.api.variant.LibraryVariantBuilder +import com.android.build.api.variant.VariantBuilder +import com.didiglobal.booster.task.spi.VariantProcessor +import com.didiglobal.booster.transform.logcat.Build.GROUP +import com.didiglobal.booster.transform.logcat.Build.VERSION +import com.google.auto.service.AutoService +import org.gradle.api.Project + +/** + * @author neighbWang + */ +@AutoService(VariantProcessor::class) +class LogcatVariantProcessor(private val project: Project) : VariantProcessor { + + override fun beforeProcess(variantBuilder: VariantBuilder) { + if (variantBuilder is LibraryVariantBuilder || variantBuilder is DynamicFeatureVariantBuilder) { + return + } + project.dependencies.add("${variantBuilder.name}Implementation", "$GROUP:booster-android-instrument-logcat:$VERSION") + } + +} diff --git a/booster-transform-logcat/src/main/kotlin/com/didiglobal/booster/transform/logcat/LogcatVarinatProcessor.kt b/booster-transform-logcat/src/main/kotlin/com/didiglobal/booster/transform/logcat/LogcatVarinatProcessor.kt deleted file mode 100644 index aac8884b9..000000000 --- a/booster-transform-logcat/src/main/kotlin/com/didiglobal/booster/transform/logcat/LogcatVarinatProcessor.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.didiglobal.booster.transform.logcat - -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.LibraryVariant -import com.didiglobal.booster.gradle.isDynamicFeature -import com.didiglobal.booster.gradle.project -import com.didiglobal.booster.task.spi.VariantProcessor -import com.google.auto.service.AutoService - -/** - * @author neighbWang - */ -@AutoService(VariantProcessor::class) -class LogcatVarinatProcessor : VariantProcessor { - - override fun process(variant: BaseVariant) { - if (variant !is LibraryVariant && !variant.isDynamicFeature) { - variant.project.dependencies.add("implementation", "${Build.GROUP}:booster-android-instrument-logcat:${Build.VERSION}") - } - } - -} diff --git a/booster-transform-media-player/build.gradle b/booster-transform-media-player/build.gradle index 463c7385e..f0bf91bf4 100644 --- a/booster-transform-media-player/build.gradle +++ b/booster-transform-media-player/build.gradle @@ -4,6 +4,6 @@ dependencies { kapt "com.google.auto.service:auto-service:1.0" implementation project(':booster-api') implementation project(':booster-transform-asm') - compileOnly 'com.android.tools.build:gradle:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' + compileOnly 'com.android.tools.build:gradle:8.0.0' + testCompileOnly 'com.android.tools.build:gradle:8.0.0' } diff --git a/booster-transform-media-player/src/main/kotlin/com/didiglobal/booster/transform/mediaplayer/MediaPlayerTransformer.kt b/booster-transform-media-player/src/main/kotlin/com/didiglobal/booster/transform/mediaplayer/MediaPlayerTransformer.kt index 6b5dce064..381a47364 100644 --- a/booster-transform-media-player/src/main/kotlin/com/didiglobal/booster/transform/mediaplayer/MediaPlayerTransformer.kt +++ b/booster-transform-media-player/src/main/kotlin/com/didiglobal/booster/transform/mediaplayer/MediaPlayerTransformer.kt @@ -6,6 +6,7 @@ import com.didiglobal.booster.transform.TransformContext import com.didiglobal.booster.transform.asm.ClassTransformer import com.didiglobal.booster.transform.asm.transform import com.didiglobal.booster.transform.media.player.Build +import com.didiglobal.booster.transform.media.player.Build.* import com.google.auto.service.AutoService import org.objectweb.asm.Opcodes import org.objectweb.asm.tree.ClassNode @@ -25,7 +26,7 @@ class MediaPlayerTransformer : ClassTransformer { private lateinit var logger: PrintWriter - override val name: String = Build.ARTIFACT + override val name: String = ARTIFACT override fun onPreTransform(context: TransformContext) { this.logger = getReport(context, "report.txt").touch().printWriter() diff --git a/booster-transform-media-player/src/main/kotlin/com/didiglobal/booster/transform/mediaplayer/MediaPlayerVariantProcessor.kt b/booster-transform-media-player/src/main/kotlin/com/didiglobal/booster/transform/mediaplayer/MediaPlayerVariantProcessor.kt new file mode 100644 index 000000000..f446679d8 --- /dev/null +++ b/booster-transform-media-player/src/main/kotlin/com/didiglobal/booster/transform/mediaplayer/MediaPlayerVariantProcessor.kt @@ -0,0 +1,25 @@ +package com.didiglobal.booster.transform.mediaplayer + +import com.android.build.api.variant.DynamicFeatureVariantBuilder +import com.android.build.api.variant.LibraryVariantBuilder +import com.android.build.api.variant.VariantBuilder +import com.didiglobal.booster.task.spi.VariantProcessor +import com.didiglobal.booster.transform.media.player.Build.GROUP +import com.didiglobal.booster.transform.media.player.Build.VERSION +import com.google.auto.service.AutoService +import org.gradle.api.Project + +/** + * @author neighbWang + */ +@AutoService(VariantProcessor::class) +class MediaPlayerVariantProcessor(private val project: Project) : VariantProcessor { + + override fun beforeProcess(variantBuilder: VariantBuilder) { + if (variantBuilder is LibraryVariantBuilder || variantBuilder is DynamicFeatureVariantBuilder) { + return + } + project.dependencies.add("${variantBuilder.name}Implementation", "$GROUP:booster-android-instrument-media-player:$VERSION") + } + +} diff --git a/booster-transform-media-player/src/main/kotlin/com/didiglobal/booster/transform/mediaplayer/MediaPlayerVarinatProcessor.kt b/booster-transform-media-player/src/main/kotlin/com/didiglobal/booster/transform/mediaplayer/MediaPlayerVarinatProcessor.kt deleted file mode 100644 index c6501227e..000000000 --- a/booster-transform-media-player/src/main/kotlin/com/didiglobal/booster/transform/mediaplayer/MediaPlayerVarinatProcessor.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.didiglobal.booster.transform.mediaplayer - -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.LibraryVariant -import com.didiglobal.booster.gradle.isDynamicFeature -import com.didiglobal.booster.gradle.project -import com.didiglobal.booster.task.spi.VariantProcessor -import com.didiglobal.booster.transform.media.player.Build -import com.google.auto.service.AutoService - -/** - * @author neighbWang - */ -@AutoService(VariantProcessor::class) -class MediaPlayerVarinatProcessor : VariantProcessor { - - override fun process(variant: BaseVariant) { - if (variant !is LibraryVariant && !variant.isDynamicFeature) { - variant.project.dependencies.add("implementation", "${Build.GROUP}:booster-android-instrument-media-player:${Build.VERSION}") - } - } - -} diff --git a/booster-transform-r-inline/src/main/kotlin/com/didiglobal/booster/transform/r/inline/RInlineTransformer.kt b/booster-transform-r-inline/src/main/kotlin/com/didiglobal/booster/transform/r/inline/RInlineTransformer.kt index d6bc0e3b4..570e95bd2 100644 --- a/booster-transform-r-inline/src/main/kotlin/com/didiglobal/booster/transform/r/inline/RInlineTransformer.kt +++ b/booster-transform-r-inline/src/main/kotlin/com/didiglobal/booster/transform/r/inline/RInlineTransformer.kt @@ -9,6 +9,7 @@ import com.didiglobal.booster.transform.ArtifactManager.Companion.MERGED_RES import com.didiglobal.booster.transform.ArtifactManager.Companion.SYMBOL_LIST import com.didiglobal.booster.transform.TransformContext import com.didiglobal.booster.transform.asm.ClassTransformer +import com.didiglobal.booster.transform.r.inline.Build.* import com.google.auto.service.AutoService import org.gradle.api.logging.Logging import org.objectweb.asm.ClassWriter @@ -43,7 +44,7 @@ class RInlineTransformer : ClassTransformer { ConcurrentHashMap() } - override val name: String = Build.ARTIFACT + override val name: String = ARTIFACT override fun onPreTransform(context: TransformContext) { this.appPackage = context.originalApplicationId.replace('.', '/') @@ -169,7 +170,7 @@ private fun TransformContext.findRetainedSymbols(): Set { }.flatten().toSet() } -private val PROPERTY_PREFIX = Build.ARTIFACT.replace('-', '.') +private val PROPERTY_PREFIX = ARTIFACT.replace('-', '.') private val PROPERTY_IGNORES = "$PROPERTY_PREFIX.ignores" diff --git a/booster-transform-res-check/build.gradle b/booster-transform-res-check/build.gradle index 463c7385e..f0bf91bf4 100644 --- a/booster-transform-res-check/build.gradle +++ b/booster-transform-res-check/build.gradle @@ -4,6 +4,6 @@ dependencies { kapt "com.google.auto.service:auto-service:1.0" implementation project(':booster-api') implementation project(':booster-transform-asm') - compileOnly 'com.android.tools.build:gradle:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' + compileOnly 'com.android.tools.build:gradle:8.0.0' + testCompileOnly 'com.android.tools.build:gradle:8.0.0' } diff --git a/booster-transform-res-check/src/main/kotlin/com/didiglobal/booster/transform/res/check/ResCheckVariantProcessor.kt b/booster-transform-res-check/src/main/kotlin/com/didiglobal/booster/transform/res/check/ResCheckVariantProcessor.kt new file mode 100644 index 000000000..e89faf946 --- /dev/null +++ b/booster-transform-res-check/src/main/kotlin/com/didiglobal/booster/transform/res/check/ResCheckVariantProcessor.kt @@ -0,0 +1,25 @@ +package com.didiglobal.booster.transform.res.check + +import com.android.build.api.variant.DynamicFeatureVariantBuilder +import com.android.build.api.variant.LibraryVariantBuilder +import com.android.build.api.variant.VariantBuilder +import com.didiglobal.booster.task.spi.VariantProcessor +import com.didiglobal.booster.transform.res.check.Build.GROUP +import com.didiglobal.booster.transform.res.check.Build.VERSION +import com.google.auto.service.AutoService +import org.gradle.api.Project + +/** + * @author neighbWang + */ +@AutoService(VariantProcessor::class) +class ResCheckVariantProcessor(private val project: Project) : VariantProcessor { + + override fun beforeProcess(variantBuilder: VariantBuilder) { + if (variantBuilder is LibraryVariantBuilder || variantBuilder is DynamicFeatureVariantBuilder) { + return + } + project.dependencies.add("${variantBuilder.name}Implementation", "$GROUP:booster-android-instrument-res-check:$VERSION") + } + +} diff --git a/booster-transform-res-check/src/main/kotlin/com/didiglobal/booster/transform/res/check/ResCheckVarinatProcessor.kt b/booster-transform-res-check/src/main/kotlin/com/didiglobal/booster/transform/res/check/ResCheckVarinatProcessor.kt deleted file mode 100644 index e1b9ecd15..000000000 --- a/booster-transform-res-check/src/main/kotlin/com/didiglobal/booster/transform/res/check/ResCheckVarinatProcessor.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.didiglobal.booster.transform.res.check - -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.LibraryVariant -import com.didiglobal.booster.gradle.isDynamicFeature -import com.didiglobal.booster.gradle.project -import com.didiglobal.booster.task.spi.VariantProcessor -import com.google.auto.service.AutoService - -/** - * @author neighbWang - */ -@AutoService(VariantProcessor::class) -class ResCheckVarinatProcessor : VariantProcessor { - - override fun process(variant: BaseVariant) { - if (variant !is LibraryVariant && !variant.isDynamicFeature) { - variant.project.dependencies.add("implementation", "${Build.GROUP}:booster-android-instrument-res-check:${Build.VERSION}") - } - } - -} diff --git a/booster-transform-service-loader/README.md b/booster-transform-service-loader/README.md deleted file mode 100644 index f114cedd2..000000000 --- a/booster-transform-service-loader/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# booster-transform-service-loader - -This module is used for `ServiceLoader` optimization on Android, as we known, JDK provided `ServiceLoader` since Java 1.5, due the different implementation, using `ServiceLoader` on Android platform will cause performance issue, booster trying to fix this problem by manipulate the bytecode. - -Android R8 also provides `ServiceLoader` optimization, due to the compatibility issues, there are still some apps have not migrate from Proguard to R8, in this case, this module can be an alternative of R8. - -To enable `ServiceLoader` optimization, the invocation of `ServiceLoader` must be follow the following pattern: - -```java -ServiceLoader.load(Service.class).iterator() -``` - -After optimization, the code will be - -```java -Arrays.asList(new Service[] { new A(), new B() }).iterator() -``` diff --git a/booster-transform-service-loader/build.gradle b/booster-transform-service-loader/build.gradle deleted file mode 100644 index 463c7385e..000000000 --- a/booster-transform-service-loader/build.gradle +++ /dev/null @@ -1,9 +0,0 @@ -apply from: "$rootDir/gradle/booster.gradle" - -dependencies { - kapt "com.google.auto.service:auto-service:1.0" - implementation project(':booster-api') - implementation project(':booster-transform-asm') - compileOnly 'com.android.tools.build:gradle:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' -} diff --git a/booster-transform-service-loader/src/main/kotlin/com/didiglobal/booster/transform/serviceloader/ServiceLoaderTransformer.kt b/booster-transform-service-loader/src/main/kotlin/com/didiglobal/booster/transform/serviceloader/ServiceLoaderTransformer.kt deleted file mode 100644 index 41aeb5c01..000000000 --- a/booster-transform-service-loader/src/main/kotlin/com/didiglobal/booster/transform/serviceloader/ServiceLoaderTransformer.kt +++ /dev/null @@ -1,176 +0,0 @@ -package com.didiglobal.booster.transform.serviceloader - -import com.didiglobal.booster.kotlinx.search -import com.didiglobal.booster.kotlinx.touch -import com.didiglobal.booster.transform.TransformContext -import com.didiglobal.booster.transform.asm.ClassTransformer -import com.didiglobal.booster.transform.asm.asIterable -import com.didiglobal.booster.transform.service.loader.Build -import com.google.auto.service.AutoService -import org.objectweb.asm.Opcodes -import org.objectweb.asm.Type -import org.objectweb.asm.tree.AbstractInsnNode -import org.objectweb.asm.tree.ClassNode -import org.objectweb.asm.tree.InsnList -import org.objectweb.asm.tree.InsnNode -import org.objectweb.asm.tree.LdcInsnNode -import org.objectweb.asm.tree.MethodInsnNode -import org.objectweb.asm.tree.MethodNode -import org.objectweb.asm.tree.TypeInsnNode -import org.objectweb.asm.tree.VarInsnNode -import java.io.File -import java.io.PrintWriter -import java.util.Locale -import java.util.zip.ZipEntry -import java.util.zip.ZipFile - -@AutoService(ClassTransformer::class) -class ServiceLoaderTransformer : ClassTransformer { - - private lateinit var logger: PrintWriter - private lateinit var services: Map> - - override val name: String = Build.ARTIFACT - - override fun onPreTransform(context: TransformContext) { - this.services = context.compileClasspath.map(File::services).flatten().toMap() - this.logger = getReport(context, "report.txt").touch().printWriter() - } - - override fun onPostTransform(context: TransformContext) { - this.logger.close() - } - - override fun transform(context: TransformContext, klass: ClassNode): ClassNode { - if (services.isNotEmpty()) { - klass.methods.forEach { method -> - method.instructions.asIterable() - .filterIsInstance() - .filter(::isServiceLoaderLoad) - .forEach { - when (it.desc) { - // java/util/ServiceLoader.load:(Ljava/lang/Class;)Ljava/util/ServiceLoader; - "(L${JAVA_LANG_CLASS};)L${JAVA_UTIL_SERVICE_LOADER};" -> transformServiceLoader(method, it, false) - // java/util/ServiceLoader.load:(Ljava/lang/Class;Ljava/lang/ClassLoader;)Ljava/util/ServiceLoader; - "(L${JAVA_LANG_CLASS};L${JAVA_LANG_CLASS_LOADER};)L${JAVA_UTIL_SERVICE_LOADER};" -> transformServiceLoader(method, it, true) - } - } - } - } - return klass - } - - /** - * ServiceLoader.load(Service.class, ...).iterator() => Arrays.asList(new Service[] { new A(), new B(), new C(), ...}).iterator() - */ - private fun transformServiceLoader(method: MethodNode, invoke: MethodInsnNode, hasClassLoader: Boolean) { - val service = ((invoke.previous as? LdcInsnNode)?.cst as? Type)?.className ?: return - val implementations = services[service]?.takeIf(Collection::isNotEmpty)?.map { - it.replace('.', '/') - } ?: return - - method.instructions.apply { - // consume the arguments of ServiceLoader.load(...) - insertBefore(invoke, InsnNode(if (hasClassLoader) Opcodes.POP2 else Opcodes.POP)) - insertBefore(invoke, InsnList().apply { - // array length - add(implementations.size.insn) - // new Service[] { ... } - add(TypeInsnNode(Opcodes.ANEWARRAY, service.replace('.', '/'))) - implementations.withIndex().forEach { (index, implementation) -> - /* dup */ add(InsnNode(Opcodes.DUP)) - /* iconst_x/bipush */ add(index.insn) - /* new */ add(TypeInsnNode(Opcodes.NEW, implementation)) - /* dup */ add(InsnNode(Opcodes.DUP)) - /* invokespecial */ add(MethodInsnNode(Opcodes.INVOKESPECIAL, implementation, "", "()V")) - /* aastore */ add(InsnNode(Opcodes.AASTORE)) - } - add(MethodInsnNode(Opcodes.INVOKESTATIC, JAVA_UTIL_ARRAYS, "asList", "([L${JAVA_LANG_OBJECT};)L${JAVA_UTIL_LIST};")) - }) - (invoke.next as MethodInsnNode).apply { - opcode = Opcodes.INVOKEINTERFACE - owner = JAVA_UTIL_LIST - itf = true - } - remove(invoke) - } - logger.println("* ${JAVA_UTIL_SERVICE_LOADER}.load(L${JAVA_LANG_CLASS};${ - if (hasClassLoader) "L${JAVA_LANG_CLASS_LOADER};" else "" - }) => ${JAVA_UTIL_ARRAYS}.asList(new ${service}[] {${implementations.joinToString(", ") { - "new ${it}()" - }})L${JAVA_UTIL_LIST};") - } - - - /** - * ldc #? // Class ... - * invokestatic #? // Method java/util/ServiceLoader.load:(Ljava/lang/Class;)Ljava/util/ServiceLoader; - * invokevirtual #? // Method java/util/ServiceLoader.iterator:()Ljava/util/Iterator; - */ - private fun isServiceLoaderLoad(invoke: MethodInsnNode): Boolean { - val prev = (invoke.previous as? LdcInsnNode) ?: return false - val next = invoke.next as? MethodInsnNode ?: return false - return invoke.opcode == Opcodes.INVOKESTATIC - && invoke.owner == JAVA_UTIL_SERVICE_LOADER - && invoke.name == "load" - && invoke.desc == "(L${JAVA_LANG_CLASS};)L${JAVA_UTIL_SERVICE_LOADER};" - && (prev.cst as? Type)?.className in services.keys - && next.owner == JAVA_UTIL_SERVICE_LOADER - && next.name == "iterator" - && next.desc == "()L${JAVA_UTIL_ITERATOR};" - } - -} - -private val Int.insn: AbstractInsnNode - get() = when (this) { - 0 -> InsnNode(Opcodes.ICONST_0) - 1 -> InsnNode(Opcodes.ICONST_1) - 2 -> InsnNode(Opcodes.ICONST_2) - 3 -> InsnNode(Opcodes.ICONST_3) - 4 -> InsnNode(Opcodes.ICONST_4) - 5 -> InsnNode(Opcodes.ICONST_5) - else -> VarInsnNode(Opcodes.BIPUSH, this) - } - -private val List.services: Set - get() = filter { line -> - line.startsWith("#") || line.isNotBlank() - }.map(String::trim).toSet() - -private val File.services: List>> - get() = when { - isDirectory -> search { - it.isFile && it.parentFile?.name == "services" && it.parentFile?.parentFile?.name == "META-INF" - }.map { spi -> - spi.name to spi.readLines().services - } - isFile -> when (extension.lowercase()) { - "jar" -> ZipFile(this).use { zip -> - zip.entries() - .asSequence() - .toList() - .filterNot(ZipEntry::isDirectory) - .filter { - it.name.startsWith(SPI_PREFIX) && it.name.length > SPI_PREFIX.length - }.map { - it.name.substringAfter(SPI_PREFIX) to zip.getInputStream(it) - .bufferedReader().readLines().services - } - }.toList() - else -> emptyList() - } - else -> emptyList() - } - -private const val DIR_META_INF = "META-INF" -private const val DIR_SERVICES = "services" -private const val SPI_PREFIX = "${DIR_META_INF}/${DIR_SERVICES}/" - -private const val JAVA_LANG_CLASS = "java/lang/Class" -private const val JAVA_LANG_OBJECT = "java/lang/Object" -private const val JAVA_LANG_CLASS_LOADER = "java/lang/ClassLoader" -private const val JAVA_UTIL_ARRAYS = "java/util/Arrays" -private const val JAVA_UTIL_ITERATOR = "java/util/Iterator" -private const val JAVA_UTIL_LIST = "java/util/List" -private const val JAVA_UTIL_SERVICE_LOADER = "java/util/ServiceLoader" diff --git a/booster-transform-shared-preferences/build.gradle b/booster-transform-shared-preferences/build.gradle deleted file mode 100644 index 463c7385e..000000000 --- a/booster-transform-shared-preferences/build.gradle +++ /dev/null @@ -1,9 +0,0 @@ -apply from: "$rootDir/gradle/booster.gradle" - -dependencies { - kapt "com.google.auto.service:auto-service:1.0" - implementation project(':booster-api') - implementation project(':booster-transform-asm') - compileOnly 'com.android.tools.build:gradle:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' -} diff --git a/booster-transform-shared-preferences/src/main/kotlin/com/didiglobal/booster/transform/sharedpreferences/SharedPreferencesTransformer.kt b/booster-transform-shared-preferences/src/main/kotlin/com/didiglobal/booster/transform/sharedpreferences/SharedPreferencesTransformer.kt deleted file mode 100644 index c0b6736ef..000000000 --- a/booster-transform-shared-preferences/src/main/kotlin/com/didiglobal/booster/transform/sharedpreferences/SharedPreferencesTransformer.kt +++ /dev/null @@ -1,93 +0,0 @@ -package com.didiglobal.booster.transform.sharedpreferences - -import com.didiglobal.booster.kotlinx.asIterable -import com.didiglobal.booster.kotlinx.touch -import com.didiglobal.booster.transform.ArtifactManager -import com.didiglobal.booster.transform.TransformContext -import com.didiglobal.booster.transform.asm.ClassTransformer -import com.didiglobal.booster.transform.shared.preferences.Build -import com.didiglobal.booster.transform.util.ComponentHandler -import com.google.auto.service.AutoService -import org.objectweb.asm.Opcodes.INVOKESTATIC -import org.objectweb.asm.Opcodes.INVOKEVIRTUAL -import org.objectweb.asm.tree.ClassNode -import org.objectweb.asm.tree.MethodInsnNode -import java.io.PrintWriter -import javax.xml.parsers.SAXParserFactory - -/** - * Represents a transformer for *SharedPreferences* optimization - * - * @author neighbWang - */ -@AutoService(ClassTransformer::class) -class SharedPreferencesTransformer : ClassTransformer { - - private lateinit var logger: PrintWriter - private val applications = mutableSetOf() - - override val name: String = Build.ARTIFACT - - override fun onPreTransform(context: TransformContext) { - val parser = SAXParserFactory.newInstance().newSAXParser() - context.artifacts.get(ArtifactManager.MERGED_MANIFESTS).forEach { manifest -> - val handler = ComponentHandler() - parser.parse(manifest, handler) - applications.addAll(handler.applications) - } - logger = getReport(context, "report.txt").touch().printWriter() - } - - override fun onPostTransform(context: TransformContext) { - logger.close() - } - - override fun transform(context: TransformContext, klass: ClassNode): ClassNode { - if (klass.name.startsWith(BOOSTER_DIRECTORY_PREFIX) - || klass.name.startsWith(SUPPORT_MULTIDEX_PACKAGE_PREFIX) - || klass.name.startsWith(JETPACK_MULTIDEX_PACKAGE_PREFIX)) { - return klass - } - - klass.methods.forEach { method -> - method.instructions.iterator().asIterable().filter { - it.opcode == INVOKEVIRTUAL || it.opcode == INVOKESTATIC - }.map { - it as MethodInsnNode - }.forEach { - mapOf( - CONTEXT_GET_SHARED_PREFERENCES to SHADOW_CONTEXT_GET_SHARED_PREFERENCES, - ACTIVITY_GET_PREFERENCES to SHADOW_ACTIVITY_GET_PREFERENCES, - PREFERENCE_MANAGER_GET_DEFAULT_SHARED_PREFERENCES to SHADOW_PREFERENCE_MANAGER_GET_DEFAULT_SHARED_PREFERENCES - ).forEach { (original, shadow) -> - if (it.opcode == original.opcode && it.name == original.name && it.desc == original.desc && context.klassPool.get(original.owner).isAssignableFrom(it.owner)) { - logger.println(" * ${shadow.owner}${shadow.name}${shadow.desc} => ${it.owner}.${it.name}${it.desc}: ${klass.name}.${method.name}${method.desc}") - it.opcode = shadow.opcode - it.owner = shadow.owner - it.name = shadow.name - it.desc = shadow.desc - } - } - } - } - return klass - } -} - -private const val ACTIVITY = "android/app/Activity" -private const val CONTEXT = "android/content/Context" -private const val PREFERENCE_MANAGER = "android.preference/PreferenceManager" -private const val SHARED_PREFERENCES = "android/content/SharedPreferences" -private const val SUPPORT_MULTIDEX_PACKAGE_PREFIX = "android/support/multidex/" -private const val JETPACK_MULTIDEX_PACKAGE_PREFIX = "androidx/multidex/" -private const val BOOSTER_DIRECTORY_PREFIX = "com/didiglobal/booster/instrument" -private const val SHADOW_SHARED_PREFERENCES = "$BOOSTER_DIRECTORY_PREFIX/ShadowSharedPreferences" - -private val CONTEXT_GET_SHARED_PREFERENCES = MethodInsnNode(INVOKEVIRTUAL, CONTEXT, "getSharedPreferences", "(Ljava/lang/String;I)L$SHARED_PREFERENCES;") -private val SHADOW_CONTEXT_GET_SHARED_PREFERENCES = MethodInsnNode(INVOKESTATIC, SHADOW_SHARED_PREFERENCES, "getSharedPreferences", "(L$CONTEXT;Ljava/lang/String;I)L$SHARED_PREFERENCES;") - -private val PREFERENCE_MANAGER_GET_DEFAULT_SHARED_PREFERENCES = MethodInsnNode(INVOKESTATIC, PREFERENCE_MANAGER, "getDefaultSharedPreferences", "(L$CONTEXT;)L$SHARED_PREFERENCES;") -private val SHADOW_PREFERENCE_MANAGER_GET_DEFAULT_SHARED_PREFERENCES = MethodInsnNode(INVOKESTATIC, SHADOW_SHARED_PREFERENCES, "getDefaultSharedPreferences", "(L$CONTEXT;)L$SHARED_PREFERENCES;") - -private val ACTIVITY_GET_PREFERENCES = MethodInsnNode(INVOKEVIRTUAL, ACTIVITY, "getPreferences", "(I)L$SHARED_PREFERENCES;") -private val SHADOW_ACTIVITY_GET_PREFERENCES = MethodInsnNode(INVOKESTATIC, SHADOW_SHARED_PREFERENCES, "getPreferences", "(L$ACTIVITY;I)L$SHARED_PREFERENCES;") diff --git a/booster-transform-shared-preferences/src/main/kotlin/com/didiglobal/booster/transform/sharedpreferences/SharedPreferencesVariantProcessor.kt b/booster-transform-shared-preferences/src/main/kotlin/com/didiglobal/booster/transform/sharedpreferences/SharedPreferencesVariantProcessor.kt deleted file mode 100644 index 1f4398b5d..000000000 --- a/booster-transform-shared-preferences/src/main/kotlin/com/didiglobal/booster/transform/sharedpreferences/SharedPreferencesVariantProcessor.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.didiglobal.booster.transform.sharedpreferences - -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.LibraryVariant -import com.didiglobal.booster.gradle.isDynamicFeature -import com.didiglobal.booster.gradle.project -import com.didiglobal.booster.task.spi.VariantProcessor -import com.didiglobal.booster.transform.shared.preferences.Build -import com.google.auto.service.AutoService - -/** - * @author neighbWang - */ -@AutoService(VariantProcessor::class) -class SharedPreferencesVariantProcessor : VariantProcessor { - - override fun process(variant: BaseVariant) { - if (variant !is LibraryVariant && !variant.isDynamicFeature) { - variant.project.dependencies.add("implementation", "${Build.GROUP}:booster-android-instrument-shared-preferences:${Build.VERSION}") - } - } - -} diff --git a/booster-transform-thread/build.gradle b/booster-transform-thread/build.gradle index 463c7385e..f0bf91bf4 100644 --- a/booster-transform-thread/build.gradle +++ b/booster-transform-thread/build.gradle @@ -4,6 +4,6 @@ dependencies { kapt "com.google.auto.service:auto-service:1.0" implementation project(':booster-api') implementation project(':booster-transform-asm') - compileOnly 'com.android.tools.build:gradle:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' + compileOnly 'com.android.tools.build:gradle:8.0.0' + testCompileOnly 'com.android.tools.build:gradle:8.0.0' } diff --git a/booster-transform-thread/src/main/kotlin/com/didiglobal/booster/transform/thread/ThreadVariantProcessor.kt b/booster-transform-thread/src/main/kotlin/com/didiglobal/booster/transform/thread/ThreadVariantProcessor.kt index 3d83a7e9b..aa5a01ab8 100644 --- a/booster-transform-thread/src/main/kotlin/com/didiglobal/booster/transform/thread/ThreadVariantProcessor.kt +++ b/booster-transform-thread/src/main/kotlin/com/didiglobal/booster/transform/thread/ThreadVariantProcessor.kt @@ -1,19 +1,22 @@ package com.didiglobal.booster.transform.thread -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.LibraryVariant -import com.didiglobal.booster.gradle.isDynamicFeature -import com.didiglobal.booster.gradle.project +import com.android.build.api.variant.DynamicFeatureVariantBuilder +import com.android.build.api.variant.LibraryVariantBuilder +import com.android.build.api.variant.VariantBuilder import com.didiglobal.booster.task.spi.VariantProcessor +import com.didiglobal.booster.transform.thread.Build.GROUP +import com.didiglobal.booster.transform.thread.Build.VERSION import com.google.auto.service.AutoService +import org.gradle.api.Project @AutoService(VariantProcessor::class) -class ThreadVariantProcessor : VariantProcessor { +class ThreadVariantProcessor(private val project: Project) : VariantProcessor { - override fun process(variant: BaseVariant) { - if (variant !is LibraryVariant && !variant.isDynamicFeature) { - variant.project.dependencies.add("implementation", "${Build.GROUP}:booster-android-instrument-thread:${Build.VERSION}") + override fun beforeProcess(variantBuilder: VariantBuilder) { + if (variantBuilder is LibraryVariantBuilder || variantBuilder is DynamicFeatureVariantBuilder) { + return } + project.dependencies.add("${variantBuilder.name}Implementation", "$GROUP:booster-android-instrument-thread:$VERSION") } } diff --git a/booster-transform-toast/build.gradle b/booster-transform-toast/build.gradle index 463c7385e..f0bf91bf4 100644 --- a/booster-transform-toast/build.gradle +++ b/booster-transform-toast/build.gradle @@ -4,6 +4,6 @@ dependencies { kapt "com.google.auto.service:auto-service:1.0" implementation project(':booster-api') implementation project(':booster-transform-asm') - compileOnly 'com.android.tools.build:gradle:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' + compileOnly 'com.android.tools.build:gradle:8.0.0' + testCompileOnly 'com.android.tools.build:gradle:8.0.0' } diff --git a/booster-transform-toast/src/main/kotlin/com/didiglobal/booster/transform/toast/ToastVariantProcessor.kt b/booster-transform-toast/src/main/kotlin/com/didiglobal/booster/transform/toast/ToastVariantProcessor.kt index 53cebfc94..45170a985 100644 --- a/booster-transform-toast/src/main/kotlin/com/didiglobal/booster/transform/toast/ToastVariantProcessor.kt +++ b/booster-transform-toast/src/main/kotlin/com/didiglobal/booster/transform/toast/ToastVariantProcessor.kt @@ -1,19 +1,22 @@ package com.didiglobal.booster.transform.toast -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.LibraryVariant -import com.didiglobal.booster.gradle.isDynamicFeature -import com.didiglobal.booster.gradle.project +import com.android.build.api.variant.DynamicFeatureVariantBuilder +import com.android.build.api.variant.LibraryVariantBuilder +import com.android.build.api.variant.VariantBuilder import com.didiglobal.booster.task.spi.VariantProcessor +import com.didiglobal.booster.transform.toast.Build.GROUP +import com.didiglobal.booster.transform.toast.Build.VERSION import com.google.auto.service.AutoService +import org.gradle.api.Project @AutoService(VariantProcessor::class) -class ToastVariantProcessor : VariantProcessor { +class ToastVariantProcessor(private val project: Project) : VariantProcessor { - override fun process(variant: BaseVariant) { - if (variant !is LibraryVariant && !variant.isDynamicFeature) { - variant.project.dependencies.add("implementation", "${Build.GROUP}:booster-android-instrument-toast:${Build.VERSION}") + override fun beforeProcess(variantBuilder: VariantBuilder) { + if (variantBuilder is LibraryVariantBuilder || variantBuilder is DynamicFeatureVariantBuilder) { + return } + project.dependencies.add("${variantBuilder.name}Implementation", "$GROUP:booster-android-instrument-toast:$VERSION") } } diff --git a/booster-transform-webview/build.gradle b/booster-transform-webview/build.gradle deleted file mode 100644 index 463c7385e..000000000 --- a/booster-transform-webview/build.gradle +++ /dev/null @@ -1,9 +0,0 @@ -apply from: "$rootDir/gradle/booster.gradle" - -dependencies { - kapt "com.google.auto.service:auto-service:1.0" - implementation project(':booster-api') - implementation project(':booster-transform-asm') - compileOnly 'com.android.tools.build:gradle:4.0.0' - testCompileOnly 'com.android.tools.build:gradle:4.0.0' -} diff --git a/booster-transform-webview/src/main/kotlin/com/didiglobal/booster/transform/webview/WebViewTransformer.kt b/booster-transform-webview/src/main/kotlin/com/didiglobal/booster/transform/webview/WebViewTransformer.kt deleted file mode 100644 index 2582d4b71..000000000 --- a/booster-transform-webview/src/main/kotlin/com/didiglobal/booster/transform/webview/WebViewTransformer.kt +++ /dev/null @@ -1,86 +0,0 @@ -package com.didiglobal.booster.transform.webview - -import com.didiglobal.booster.kotlinx.touch -import com.didiglobal.booster.transform.ArtifactManager -import com.didiglobal.booster.transform.TransformContext -import com.didiglobal.booster.transform.asm.ClassTransformer -import com.didiglobal.booster.transform.asm.className -import com.didiglobal.booster.transform.asm.findAll -import com.didiglobal.booster.transform.util.ComponentHandler -import com.google.auto.service.AutoService -import org.objectweb.asm.Opcodes.ACC_PUBLIC -import org.objectweb.asm.Opcodes.ALOAD -import org.objectweb.asm.Opcodes.ATHROW -import org.objectweb.asm.Opcodes.INVOKESPECIAL -import org.objectweb.asm.Opcodes.INVOKESTATIC -import org.objectweb.asm.Opcodes.RETURN -import org.objectweb.asm.tree.ClassNode -import org.objectweb.asm.tree.InsnList -import org.objectweb.asm.tree.InsnNode -import org.objectweb.asm.tree.MethodInsnNode -import org.objectweb.asm.tree.MethodNode -import org.objectweb.asm.tree.VarInsnNode -import java.io.PrintWriter -import javax.xml.parsers.SAXParserFactory - -/** - * Represents a class transformer for application optimization - * - * @author neighbWang - */ -@AutoService(ClassTransformer::class) -class WebViewTransformer : ClassTransformer { - - private lateinit var logger: PrintWriter - private val applications = mutableSetOf() - - override val name: String = Build.ARTIFACT - - override fun onPreTransform(context: TransformContext) { - val parser = SAXParserFactory.newInstance().newSAXParser() - context.artifacts.get(ArtifactManager.MERGED_MANIFESTS).forEach { manifest -> - val handler = ComponentHandler() - parser.parse(manifest, handler) - applications.addAll(handler.applications) - } - - this.logger = getReport(context, "report.txt").touch().printWriter() - } - - override fun onPostTransform(context: TransformContext) { - this.logger.close() - } - - override fun transform(context: TransformContext, klass: ClassNode): ClassNode { - if (!this.applications.contains(klass.className)) { - return klass - } - - val method = klass.methods?.find { - "${it.name}${it.desc}" == "onCreate()V" - } ?: klass.defaultOnCreate.also { - klass.methods.add(it) - } - - method.instructions?.let { insn -> - insn.findAll(RETURN, ATHROW).forEach { ret -> - insn.insertBefore(ret, VarInsnNode(ALOAD, 0)) - insn.insertBefore(ret, MethodInsnNode(INVOKESTATIC, SHADOW_WEBVIEW, "preloadWebView", "(Landroid/app/Application;)V", false)) - logger.println(" + $SHADOW_WEBVIEW.preloadWebView(Landroid/app/Application;)V: ${klass.name}.${method.name}${method.desc} ") - } - } - return klass - } -} - -private val ClassNode.defaultOnCreate: MethodNode - get() = MethodNode(ACC_PUBLIC, "onCreate", "()V", null, null).apply { - maxStack = 1 - instructions.add(InsnList().apply { - add(VarInsnNode(ALOAD, 0)) - add(MethodInsnNode(INVOKESPECIAL, superName, name, desc, false)) - add(InsnNode(RETURN)) - }) - } - -private const val SHADOW_WEBVIEW = "com/didiglobal/booster/instrument/ShadowWebView" diff --git a/booster-transform-webview/src/main/kotlin/com/didiglobal/booster/transform/webview/WebViewVariantProcessor.kt b/booster-transform-webview/src/main/kotlin/com/didiglobal/booster/transform/webview/WebViewVariantProcessor.kt deleted file mode 100644 index 6f26acbb1..000000000 --- a/booster-transform-webview/src/main/kotlin/com/didiglobal/booster/transform/webview/WebViewVariantProcessor.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.didiglobal.booster.transform.webview - -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.LibraryVariant -import com.didiglobal.booster.gradle.isDynamicFeature -import com.didiglobal.booster.gradle.project -import com.didiglobal.booster.task.spi.VariantProcessor -import com.google.auto.service.AutoService - -/** - * @author neighbWang - */ -@AutoService(VariantProcessor::class) -class WebViewVariantProcessor : VariantProcessor { - - override fun process(variant: BaseVariant) { - if (variant !is LibraryVariant && !variant.isDynamicFeature) { - variant.project.dependencies.add("implementation", "${Build.GROUP}:booster-android-instrument-webview:${Build.VERSION}") - } - } - -} diff --git a/build.gradle b/build.gradle index 6e87db25b..2ba2e0d67 100644 --- a/build.gradle +++ b/build.gradle @@ -26,6 +26,7 @@ apply plugin: 'io.github.gradle-nexus.publish-plugin' allprojects { project -> apply plugin: 'java' + apply plugin: 'kotlin' apply plugin: 'maven-publish' group = 'com.didiglobal.booster' @@ -37,17 +38,30 @@ allprojects { project -> mavenCentral() } + sourceSets { + main { + kotlin { + srcDirs += ['src/main/kotlin', 'src/main/java', 'build/generated/source/buildprops/main/java'] + } + } + test { + kotlin { + srcDirs += ['src/main/kotlin', 'src/main/java', 'build/generated/source/buildprops/main/java'] + } + } + } + javadoc { failOnError = false } task packageJavadoc(type: Jar) { - classifier = 'javadoc' + archiveClassifier = 'javadoc' from javadoc } task packageSources(type: Jar) { - classifier = 'sources' + archiveClassifier = 'sources' from sourceSets.main.allSource } @@ -71,11 +85,11 @@ allprojects { project -> } artifact project.packageSources { - classifier "sources" + archiveClassifier.set("sources") } artifact project.packageJavadoc { - classifier "javadoc" + archiveClassifier.set("javadoc") } pom { @@ -121,6 +135,15 @@ allprojects { project -> if (!project.hasProperty("signing.skip")) { apply plugin: 'signing' + def signingTasks = project.tasks.withType(Sign) + project.tasks.withType(PublishToMavenLocal) { + dependsOn signingTasks + } + + project.tasks.withType(PublishToMavenRepository) { + dependsOn signingTasks + } + project.signing { sign publication } diff --git a/gradle.properties b/gradle.properties index d8039ff32..30ddd9822 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ systemProp.org.gradle.internal.publish.checksums.insecure=true org.gradle.caching=true org.gradle.parallel=true -org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8 +org.gradle.jvmargs=-Xmx8192m -XX:MaxMetaspaceSize=512m -Dfile.encoding=UTF-8 diff --git a/gradle/booster.gradle b/gradle/booster.gradle index 018c906c3..ecfee980a 100644 --- a/gradle/booster.gradle +++ b/gradle/booster.gradle @@ -2,8 +2,8 @@ apply plugin: 'kotlin' apply plugin: 'kotlin-kapt' apply plugin: 'io.johnsonlee.buildprops' -sourceCompatibility = JavaVersion.VERSION_11 -targetCompatibility = JavaVersion.VERSION_11 +sourceCompatibility = JavaVersion.VERSION_17 +targetCompatibility = JavaVersion.VERSION_17 sourceSets { main { @@ -26,7 +26,7 @@ sourceSets { compileKotlin { kotlinOptions{ - jvmTarget = JavaVersion.VERSION_11 + jvmTarget = JavaVersion.VERSION_17 apiVersion = "1.5" freeCompilerArgs = ["-Xno-optimized-callable-references"] } @@ -34,7 +34,7 @@ compileKotlin { compileTestKotlin { kotlinOptions{ - jvmTarget = JavaVersion.VERSION_11 + jvmTarget = JavaVersion.VERSION_17 apiVersion = "1.5" freeCompilerArgs = ["-Xno-optimized-callable-references"] } @@ -47,3 +47,8 @@ dependencies { testImplementation "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version" testImplementation gradleTestKit() } + +project.tasks.named('packageSources') { + dependsOn ":${project.name}:generateBuildJavaFile" +} + diff --git a/gradle/functional-test.gradle b/gradle/functional-test.gradle index 389dfa56a..66be46c01 100644 --- a/gradle/functional-test.gradle +++ b/gradle/functional-test.gradle @@ -34,7 +34,7 @@ check.dependsOn functionalTest compileFunctionalTestKotlin { kotlinOptions { - jvmTarget = JavaVersion.VERSION_11 + jvmTarget = JavaVersion.VERSION_17 apiVersion = "1.5" freeCompilerArgs = ["-Xno-optimized-callable-references"] } diff --git a/gradle/integration-test.gradle b/gradle/integration-test.gradle index f942e4621..c6b5ad7de 100644 --- a/gradle/integration-test.gradle +++ b/gradle/integration-test.gradle @@ -34,7 +34,7 @@ check.dependsOn integrationTest compileIntegrationTestKotlin { kotlinOptions { - jvmTarget = JavaVersion.VERSION_11 + jvmTarget = JavaVersion.VERSION_17 apiVersion = "1.5" freeCompilerArgs = ["-Xno-optimized-callable-references"] } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8049c684f..da1db5f04 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle.kts b/settings.gradle.kts index 68a43c26a..1a886dbd5 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -23,24 +23,13 @@ include(":booster-android-instrument-finalizer-watchdog-daemon") include(":booster-android-instrument-logcat") include(":booster-android-instrument-media-player") include(":booster-android-instrument-res-check") -include(":booster-android-instrument-shared-preferences") include(":booster-android-instrument-thread") include(":booster-android-instrument-toast") -include(":booster-android-instrument-webview") include(":booster-android-gradle-api") include(":booster-android-gradle-compat") -include(":booster-android-gradle-v3_3") -include(":booster-android-gradle-v3_4") -include(":booster-android-gradle-v3_5") -include(":booster-android-gradle-v3_6") -include(":booster-android-gradle-v4_0") -include(":booster-android-gradle-v4_1") -include(":booster-android-gradle-v4_2") -include(":booster-android-gradle-v7_0") -include(":booster-android-gradle-v7_1") -include(":booster-android-gradle-v7_2") -include(":booster-android-gradle-v7_3") -include(":booster-android-gradle-v7_4") +include(":booster-android-gradle-v8_0") +include(":booster-android-gradle-v8_1") +include(":booster-android-gradle-v8_2") include(":booster-annotations") include(":booster-api") include(":booster-build") @@ -51,36 +40,25 @@ include(":booster-graph") include(":booster-graph-dot") include(":booster-graph-json") include(":booster-gradle-plugin") -include(":booster-task-analyser") -include(":booster-task-check-snapshot") -include(":booster-task-compression") -include(":booster-task-compression-cwebp") -include(":booster-task-compression-pngquant") -include(":booster-task-compression-processed-res") include(":booster-task-graph") include(":booster-task-list-artifact") include(":booster-task-list-permission") include(":booster-task-list-shared-library") -include(":booster-task-resource-deredundancy") include(":booster-task-spi") include(":booster-test") include(":booster-test-asm") include(":booster-test-javassist") include(":booster-transform-activity-thread") include(":booster-transform-asm") -include(":booster-transform-br-inline") include(":booster-transform-finalizer-watchdog-daemon") include(":booster-transform-javassist") include(":booster-transform-logcat") include(":booster-transform-media-player") include(":booster-transform-res-check") -include(":booster-transform-service-loader") -include(":booster-transform-shared-preferences") include(":booster-transform-r-inline") include(":booster-transform-spi") include(":booster-transform-thread") include(":booster-transform-toast") include(":booster-transform-usage") include(":booster-transform-util") -include(":booster-transform-webview") include(":booster-kotlinx")