Reproducible Builds (#3559)

* fix: remove ShadowJar plugin

 - unable to control file dates of archive entries

* refactor: use native Gradle "fatJar" method

* refactor: drop proguard for r8

* fix: wire up R8

* wip: remove fail-fast

* Revert "wip: remove fail-fast"

This reverts commit 5d005bf82e87c89efa5552ee8f8e9c0a569aea0d.

* fix: suppress unused proguard keep messages

* fix: require java11+ for r8
This commit is contained in:
Connor Tumbleson 2024-04-07 11:45:55 -04:00 committed by GitHub
parent 25826db417
commit e69ecb578d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 54 additions and 47 deletions

View File

@ -1,25 +1,15 @@
import proguard.gradle.ProGuardTask
val apktoolVersion: String by rootProject.extra
plugins {
alias(libs.plugins.shadow)
application
}
// Buildscript is deprecated, but the alternative approach does not support expanded properties
// https://github.com/gradle/gradle/issues/9830
// So we must hard-code the version here.
buildscript {
dependencies {
// Proguard doesn't support plugin DSL - https://github.com/Guardsquare/proguard/issues/225
classpath(libs.proguard)
}
}
val r8: Configuration by configurations.creating
dependencies {
implementation(libs.commons.cli)
implementation(project(":brut.apktool:apktool-lib"))
r8(libs.r8)
}
application {
@ -28,10 +18,9 @@ application {
tasks.run.get().workingDir = file(System.getProperty("user.dir"))
}
tasks.withType<Jar> {
manifest {
attributes["Main-Class"] = "brut.apktool.Main"
}
tasks.withType<AbstractArchiveTask>().configureEach {
isPreserveFileTimestamps = false
isReproducibleFileOrder = true
}
tasks.register<Delete>("cleanOutputDirectory") {
@ -40,34 +29,50 @@ tasks.register<Delete>("cleanOutputDirectory") {
})
}
tasks.register<ProGuardTask>("proguard") {
val shadowJar = tasks.create("shadowJar", Jar::class) {
dependsOn("build")
dependsOn("cleanOutputDirectory")
dependsOn("shadowJar")
injars(tasks.named("shadowJar").get().outputs.files)
val javaHome = System.getProperty("java.home")
if (JavaVersion.current() <= JavaVersion.VERSION_1_8) {
libraryjars("$javaHome/lib/jce.jar")
libraryjars("$javaHome/lib/rt.jar")
} else {
libraryjars(mapOf("jarfilter" to "!**.jar", "filter" to "!module-info.class"),
{
"$javaHome/jmods/"
group = "build"
description = "Creates a single executable JAR with all dependencies"
manifest.attributes["Main-Class"] = "brut.apktool.Main"
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
val dependencies = configurations
.runtimeClasspath
.get()
.map(::zipTree)
from(dependencies)
with(tasks.jar.get())
}
tasks.register<JavaExec>("proguard") {
dependsOn("shadowJar")
onlyIf {
JavaVersion.current().isJava11Compatible
}
val proguardRules = file("proguard-rules.pro")
val originalJar = shadowJar.outputs.files.singleFile
inputs.files(originalJar.toString(), proguardRules)
outputs.file("build/libs/apktool-$apktoolVersion.jar")
classpath(r8)
mainClass.set("com.android.tools.r8.R8")
args = mutableListOf(
"--release",
"--classfile",
"--no-minification",
"--map-diagnostics:UnusedProguardKeepRuleDiagnostic", "info", "none",
"--lib", javaLauncher.get().metadata.installationPath.toString(),
"--output", outputs.files.singleFile.toString(),
"--pg-conf", proguardRules.toString(),
originalJar.toString()
)
}
dontobfuscate()
dontoptimize()
keep("class brut.apktool.Main { public static void main(java.lang.String[]); }")
keepclassmembers("enum * { public static **[] values(); public static ** valueOf(java.lang.String); }")
dontwarn("com.google.common.base.**")
dontwarn("com.google.common.collect.**")
dontwarn("com.google.common.util.**")
dontwarn("javax.xml.xpath.**")
dontnote("**")
val outPath = "build/libs/apktool-$apktoolVersion.jar"
outjars(outPath)
}
tasks.getByPath(":release").dependsOn("proguard")

View File

@ -0,0 +1,7 @@
-keep class brut.apktool.Main {
public static void main(java.lang.String[]);
}
-keepclassmembers enum * {
static **[] values();
static ** valueOf(java.lang.String);
}

View File

@ -55,7 +55,6 @@ if ("release" !in gradle.startParameter.taskNames) {
}
plugins {
alias(libs.plugins.shadow)
`java-library`
`maven-publish`
signing

View File

@ -6,8 +6,7 @@ commons_lang3 = "3.14.0"
commons_text = "1.11.0"
guava = "32.0.1-jre"
junit = "4.13.2"
proguard = "7.4.2"
shadow = "8.1.1"
r8 = "8.3.37"
smali = "3.0.5"
xmlpull = "1.1.4c"
xmlunit = "2.9.1"
@ -20,10 +19,7 @@ commons_lang3 = { module = "org.apache.commons:commons-lang3", version.ref = "co
commons_text = { module = "org.apache.commons:commons-text", version.ref = "commons_text" }
guava = { module = "com.google.guava:guava", version.ref = "guava" }
junit = { module = "junit:junit", version.ref = "junit" }
proguard = { module = "com.guardsquare:proguard-gradle", version.ref = "proguard" }
r8 = { module = "com.android.tools:r8", version.ref = "r8" }
smali = { module = "com.android.tools.smali:smali", version.ref = "smali" }
xmlpull = { module = "xpp3:xpp3", version.ref = "xmlpull" }
xmlunit = { module = "org.xmlunit:xmlunit-legacy", version.ref = "xmlunit" }
[plugins]
shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" }