diff --git a/build.gradle.kts b/build.gradle.kts index e2a6afe..cb5bcf8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -16,12 +16,14 @@ repositories { } dependencies { - implementation(gradleApi()) - implementation(gradleKotlinDsl()) + implementation(libs.android.application) implementation(libs.binary.compatibility.validator) + implementation(libs.guava) implementation(libs.kotlin) implementation(libs.kotlin.android) - implementation(libs.android.application) + + implementation(gradleApi()) + implementation(gradleKotlinDsl()) } java { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 77d7070..f040071 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,12 +4,14 @@ pluginPublish = "1.2.1" binary-compatibility-validator = "0.15.1" #noinspection GradleDependency agp = "8.2.2" # 8.3.0 causes Java verifier error: https://github.com/ReVanced/revanced-patches/issues/2818 +guava = "33.2.1-jre" [libraries] binary-compatibility-validator = { module = "org.jetbrains.kotlinx.binary-compatibility-validator:org.jetbrains.kotlinx.binary-compatibility-validator.gradle.plugin", version.ref = "binary-compatibility-validator" } kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } kotlin-android = { module = "org.jetbrains.kotlin.android:org.jetbrains.kotlin.android.gradle.plugin", version.ref = "kotlin" } android-application = { module = "com.android.application:com.android.application.gradle.plugin", version.ref = "agp" } +guava = { module = "com.google.guava:guava", version.ref = "guava" } [plugins] kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin"} diff --git a/src/main/kotlin/app/revanced/patches/gradle/PatchesPlugin.kt b/src/main/kotlin/app/revanced/patches/gradle/PatchesPlugin.kt index 754bb3e..f0d3e13 100644 --- a/src/main/kotlin/app/revanced/patches/gradle/PatchesPlugin.kt +++ b/src/main/kotlin/app/revanced/patches/gradle/PatchesPlugin.kt @@ -1,5 +1,11 @@ package app.revanced.patches.gradle +import com.android.tools.build.apkzlib.zip.ZFile +import com.android.tools.r8.CompilationMode +import com.android.tools.r8.D8 +import com.android.tools.r8.D8Command +import com.android.tools.r8.OutputMode +import com.android.tools.r8.utils.ArchiveResourceProvider import kotlinx.validation.BinaryCompatibilityValidatorPlugin import org.gradle.api.JavaVersion import org.gradle.api.Plugin @@ -12,12 +18,10 @@ import org.gradle.api.publish.maven.MavenPublication import org.gradle.api.tasks.SourceSetContainer import org.gradle.jvm.tasks.Jar import org.gradle.kotlin.dsl.get -import org.gradle.kotlin.dsl.support.listFilesOrdered import org.gradle.plugins.signing.SigningExtension import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension import org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper -import java.io.File @Suppress("unused") abstract class PatchesPlugin : Plugin { @@ -102,32 +106,32 @@ abstract class PatchesPlugin : Plugin { } /** - * Adds a task to build the DEX file of the patches and add it to the patches file to use on Android, + * Adds a task to build the DEX file of the patches and adds it to the patches file to use on Android, * adds the publishing plugin to the project to publish the patches API and * configures the publication with the "about" information from the extension. */ private fun Project.configurePublishing(patchesExtension: PatchesExtension) { - tasks.register("buildDexJar") { - it.description = "Build and add a DEX to the JAR file" - it.group = "build" + val buildAndroid = tasks.register("buildAndroid") { task -> + task.description = "Builds the project for Android by compiling to DEX and adding it to the patches file." + task.group = "build" - it.dependsOn(tasks["build"]) + task.dependsOn(tasks["jar"]) - it.doLast { - val d8 = File(System.getenv("ANDROID_HOME")).resolve("build-tools") - .listFilesOrdered().last().resolve("d8").absolutePath + task.doLast { + val workingDirectory = layout.buildDirectory.dir("revanced").get().asFile - val patchesJar = configurations["archives"].allArtifacts.files.files.first().absolutePath - val workingDirectory = layout.buildDirectory.dir("libs").get().asFile + val patchesFile = tasks["jar"].outputs.files.first() + val classesZipFile = workingDirectory.resolve("classes.zip") - exec { execSpec -> - execSpec.workingDir = workingDirectory - execSpec.commandLine = listOf(d8, "--release", patchesJar) - } + D8Command.builder() + .addProgramResourceProvider(ArchiveResourceProvider.fromArchive(patchesFile.toPath(), true)) + .setMode(CompilationMode.RELEASE) + .setOutput(classesZipFile.toPath(), OutputMode.DexIndexed) + .build() + .let(D8::run) - exec { execSpec -> - execSpec.workingDir = workingDirectory - execSpec.commandLine = listOf("zip", "-u", patchesJar, "classes.dex") + ZFile.openReadWrite(patchesFile).use { zFile -> + zFile.mergeFrom(ZFile.openReadOnly(classesZipFile)) { false } } } } @@ -167,7 +171,7 @@ abstract class PatchesPlugin : Plugin { // Used by gradle-semantic-release-plugin. // Tracking: https://github.com/KengoTODA/gradle-semantic-release-plugin/issues/435 tasks["publish"].apply { - dependsOn("buildDexJar") + dependsOn(buildAndroid) } } @@ -232,4 +236,3 @@ private fun Project.configureJarTask(patchesExtension: PatchesExtension) { } } } -