Skip to content

Commit 2597efe

Browse files
committed
fix: Build DEX from patches file by using internal APIs instead of CLIs
This commit uses D8 internal libraries which doesn't require an Android SDK anymore installed and apkzlib instead of an existing zip binary in path.
1 parent b1a00e9 commit 2597efe

File tree

3 files changed

+31
-24
lines changed

3 files changed

+31
-24
lines changed

build.gradle.kts

+5-3
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@ repositories {
1616
}
1717

1818
dependencies {
19-
implementation(gradleApi())
20-
implementation(gradleKotlinDsl())
19+
implementation(libs.android.application)
2120
implementation(libs.binary.compatibility.validator)
21+
implementation(libs.guava)
2222
implementation(libs.kotlin)
2323
implementation(libs.kotlin.android)
24-
implementation(libs.android.application)
24+
25+
implementation(gradleApi())
26+
implementation(gradleKotlinDsl())
2527
}
2628

2729
java {

gradle/libs.versions.toml

+2
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ pluginPublish = "1.2.1"
44
binary-compatibility-validator = "0.15.1"
55
#noinspection GradleDependency
66
agp = "8.2.2" # 8.3.0 causes Java verifier error: https://github.com/ReVanced/revanced-patches/issues/2818
7+
guava = "33.2.1-jre"
78

89
[libraries]
910
binary-compatibility-validator = { module = "org.jetbrains.kotlinx.binary-compatibility-validator:org.jetbrains.kotlinx.binary-compatibility-validator.gradle.plugin", version.ref = "binary-compatibility-validator" }
1011
kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
1112
kotlin-android = { module = "org.jetbrains.kotlin.android:org.jetbrains.kotlin.android.gradle.plugin", version.ref = "kotlin" }
1213
android-application = { module = "com.android.application:com.android.application.gradle.plugin", version.ref = "agp" }
14+
guava = { module = "com.google.guava:guava", version.ref = "guava" }
1315

1416
[plugins]
1517
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin"}

src/main/kotlin/app/revanced/patches/gradle/PatchesPlugin.kt

+24-21
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
package app.revanced.patches.gradle
22

3+
import com.android.tools.build.apkzlib.zip.ZFile
4+
import com.android.tools.r8.CompilationMode
5+
import com.android.tools.r8.D8
6+
import com.android.tools.r8.D8Command
7+
import com.android.tools.r8.OutputMode
8+
import com.android.tools.r8.utils.ArchiveResourceProvider
39
import kotlinx.validation.BinaryCompatibilityValidatorPlugin
410
import org.gradle.api.JavaVersion
511
import org.gradle.api.Plugin
@@ -12,12 +18,10 @@ import org.gradle.api.publish.maven.MavenPublication
1218
import org.gradle.api.tasks.SourceSetContainer
1319
import org.gradle.jvm.tasks.Jar
1420
import org.gradle.kotlin.dsl.get
15-
import org.gradle.kotlin.dsl.support.listFilesOrdered
1621
import org.gradle.plugins.signing.SigningExtension
1722
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
1823
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
1924
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper
20-
import java.io.File
2125

2226
@Suppress("unused")
2327
abstract class PatchesPlugin : Plugin<Project> {
@@ -102,32 +106,32 @@ abstract class PatchesPlugin : Plugin<Project> {
102106
}
103107

104108
/**
105-
* Adds a task to build the DEX file of the patches and add it to the patches file to use on Android,
109+
* Adds a task to build the DEX file of the patches and adds it to the patches file to use on Android,
106110
* adds the publishing plugin to the project to publish the patches API and
107111
* configures the publication with the "about" information from the extension.
108112
*/
109113
private fun Project.configurePublishing(patchesExtension: PatchesExtension) {
110-
tasks.register("buildDexJar") {
111-
it.description = "Build and add a DEX to the JAR file"
112-
it.group = "build"
114+
val buildAndroid = tasks.register("buildAndroid") { task ->
115+
task.description = "Builds the project for Android by compiling to DEX and adding it to the patches file."
116+
task.group = "build"
113117

114-
it.dependsOn(tasks["build"])
118+
task.dependsOn(tasks["jar"])
115119

116-
it.doLast {
117-
val d8 = File(System.getenv("ANDROID_HOME")).resolve("build-tools")
118-
.listFilesOrdered().last().resolve("d8").absolutePath
120+
task.doLast {
121+
val workingDirectory = layout.buildDirectory.dir("revanced").get().asFile
119122

120-
val patchesJar = configurations["archives"].allArtifacts.files.files.first().absolutePath
121-
val workingDirectory = layout.buildDirectory.dir("libs").get().asFile
123+
val patchesFile = tasks["jar"].outputs.files.first()
124+
val classesZipFile = workingDirectory.resolve("classes.zip")
122125

123-
exec { execSpec ->
124-
execSpec.workingDir = workingDirectory
125-
execSpec.commandLine = listOf(d8, "--release", patchesJar)
126-
}
126+
D8Command.builder()
127+
.addProgramResourceProvider(ArchiveResourceProvider.fromArchive(patchesFile.toPath(), true))
128+
.setMode(CompilationMode.RELEASE)
129+
.setOutput(classesZipFile.toPath(), OutputMode.DexIndexed)
130+
.build()
131+
.let(D8::run)
127132

128-
exec { execSpec ->
129-
execSpec.workingDir = workingDirectory
130-
execSpec.commandLine = listOf("zip", "-u", patchesJar, "classes.dex")
133+
ZFile.openReadWrite(patchesFile).use { zFile ->
134+
zFile.mergeFrom(ZFile.openReadOnly(classesZipFile)) { false }
131135
}
132136
}
133137
}
@@ -167,7 +171,7 @@ abstract class PatchesPlugin : Plugin<Project> {
167171
// Used by gradle-semantic-release-plugin.
168172
// Tracking: https://github.com/KengoTODA/gradle-semantic-release-plugin/issues/435
169173
tasks["publish"].apply {
170-
dependsOn("buildDexJar")
174+
dependsOn(buildAndroid)
171175
}
172176
}
173177

@@ -232,4 +236,3 @@ private fun Project.configureJarTask(patchesExtension: PatchesExtension) {
232236
}
233237
}
234238
}
235-

0 commit comments

Comments
 (0)