Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize/shrink jar size using proguard #14

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 60 additions & 3 deletions api/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import proguard.gradle.ProGuardTask

plugins {
id("com.github.gmazzo.buildconfig")
id("com.github.johnrengelman.shadow")
}

operator fun String.invoke(): String {
return (rootProject.properties[this] as String?)!!
}
operator fun String.invoke(): String = rootProject.properties[this] as? String ?: error("Property $this not found")

buildConfig {
className("ZumeConstants")
Expand All @@ -24,11 +25,67 @@ repositories {
maven("https://repo.spongepowered.org/repository/maven-public/")
}

val shade: Configuration by configurations.creating {
configurations.compileClasspath.get().extendsFrom(this)
configurations.runtimeClasspath.get().extendsFrom(this)
}

dependencies {
compileOnly("org.apache.logging.log4j:log4j-core:${"log4j_version"()}")

compileOnly("org.ow2.asm:asm-tree:${"asm_version"()}")
compileOnly("org.spongepowered:mixin:${"mixin_version"()}")

shade("blue.endless:jankson:${"jankson_version"()}")
}

val proguard = tasks.register<ProGuardTask>("proguardInternal") {
group = "internal"
outputs.upToDateWhen { false }

val jar = tasks.shadowJar.get().archiveFile.get().asFile
dependsOn(tasks.shadowJar)

injars(jar.absolutePath)
outjars(jar.absolutePath)

dontwarn("java.lang.invoke.MethodHandle")
allowaccessmodification()
optimizationpasses(10) // 10 is a lot but if nothing happens after a pass, it will stop
dontusemixedcaseclassnames()
keepattributes("RuntimeVisibleAnnotations")
overloadaggressively()

val javaHome = System.getProperty("java.home")
// add the jdk (base and desktop) to the libraries
libraryjars(mapOf(
"jarfilter" to "!**.jar",
"filter" to "!module-info.class"
), arrayOf("$javaHome/jmods/java.base.jmod", "$javaHome/jmods/java.desktop.jmod"))

configurations.compileClasspath.get().forEach { file ->
libraryjars(mapOf(
"jarfilter" to "!**.jar",
"filter" to "!module-info.class"
), file.absolutePath)
}

keep("class dev.nolij.zume.api.** { *; }")
keepclassmembers("class ** { @blue.endless.jankson.Comment <fields>; }")
keep("class dev.nolij.zume.ZumeMixinPlugin { *; }")

printmapping(layout.buildDirectory.dir("proguard").get().file("mapping.txt").asFile.apply {
parentFile.mkdirs()
if(exists()) delete()
createNewFile()
})
repackageclasses("dev.nolij.zume")
}

tasks.register<Jar>("proguard") {
group = "build"
dependsOn(proguard)
(archiveFile as RegularFileProperty).set(proguard.get().outJarFiles.single() as File)
}

tasks.processResources {
Expand Down
Binary file modified api/src/main/resources/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed api/src/main/resources/icon_large.png
Binary file not shown.
4 changes: 1 addition & 3 deletions archaic/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import xyz.wagyourtail.unimined.api.minecraft.task.RemapJarTask

operator fun String.invoke(): String {
return (rootProject.properties[this] as String?)!!
}
operator fun String.invoke(): String = rootProject.properties[this] as? String ?: error("Property $this not found")

unimined.minecraft {
version("archaic_minecraft_version"())
Expand Down
90 changes: 49 additions & 41 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import okhttp3.internal.immutableListOf
import org.objectweb.asm.ClassReader
import org.objectweb.asm.ClassWriter
import org.objectweb.asm.tree.ClassNode
import proguard.gradle.ProGuardTask
import xyz.wagyourtail.unimined.api.minecraft.task.RemapJarTask
import java.time.ZonedDateTime

Expand All @@ -39,6 +40,7 @@ enum class ReleaseChannel(
val deflation: JarShrinkingType,
val classes: ClassShrinkingType,
val json: JsonShrinkingType,
val proguard: Boolean = false
) {
DEV_BUILD(
suffix = "dev",
Expand All @@ -54,16 +56,18 @@ enum class ReleaseChannel(
suffix = "rc",
deflation = JarShrinkingType.SEVENZIP,
classes = ClassShrinkingType.STRIP_ALL,
json = JsonShrinkingType.MINIFY),
json = JsonShrinkingType.MINIFY,
proguard = true),
RELEASE(
releaseType = ReleaseType.STABLE,
deflation = JarShrinkingType.SEVENZIP,
classes = ClassShrinkingType.STRIP_ALL,
json = JsonShrinkingType.MINIFY),
json = JsonShrinkingType.MINIFY,
proguard = false),
}

val isRelease = rootProject.hasProperty("release_channel")
val releaseChannel = if (isRelease) ReleaseChannel.valueOf("release_channel"()) else ReleaseChannel.DEV_BUILD
val releaseChannel = if (isRelease) ReleaseChannel.valueOf("release_channel"().uppercase()) else ReleaseChannel.DEV_BUILD

println("Release Channel: $releaseChannel")

Expand Down Expand Up @@ -156,24 +160,22 @@ allprojects {
}
maven("https://repo.spongepowered.org/maven")
maven("https://jitpack.io/")
maven("https://api.modrinth.com/maven") {
content {
includeGroup("maven.modrinth")
}
exclusiveContent {
forRepository { maven("https://api.modrinth.com/maven") }
filter { includeGroup("maven.modrinth") }
}
}

tasks.withType<JavaCompile> {
if (name !in arrayOf("compileMcLauncherJava", "compilePatchedMcJava")) {
options.encoding = "UTF-8"
sourceCompatibility = "21"
options.release = 8
javaCompiler = javaToolchains.compilerFor {
languageVersion = JavaLanguageVersion.of(21)
}
if (name in arrayOf("compileMcLauncherJava", "compilePatchedMcJava")) return@withType
options.encoding = "UTF-8"
sourceCompatibility = "21"
options.release = 8
javaCompiler = javaToolchains.compilerFor {
languageVersion = JavaLanguageVersion.of(21)
}
}

dependencies {
compileOnly("org.jetbrains:annotations:${"jetbrains_annotations_version"()}")
"com.pkware.jabel:jabel-javac-plugin:${"jabel_version"()}".also {
Expand Down Expand Up @@ -218,18 +220,19 @@ subprojects {
if (implName in uniminedImpls) {
apply(plugin = "xyz.wagyourtail.unimined")
apply(plugin = "com.github.johnrengelman.shadow")
apply(plugin = "dev.nolij.zume-proguard")

configurations {
val shade = create("shade")

compileClasspath.get().extendsFrom(shade)
runtimeClasspath.get().extendsFrom(shade)
val shade: Configuration by configurations.creating {
configurations.compileClasspath.get().extendsFrom(this)
configurations.runtimeClasspath.get().extendsFrom(this)
}

tasks.jar {
destinationDirectory = subProject.layout.buildDirectory.dir("devlibs")
}

dependencies {
"shade"("blue.endless:jankson:${"jankson_version"()}") { isTransitive = false }

"shade"(project(":api")) { isTransitive = false }
shade(project(path = ":api", configuration = "proguard")) { isTransitive = false }
}

afterEvaluate {
Expand All @@ -240,11 +243,11 @@ subprojects {
rename { "${it}_${"mod_id"()}" }
}

val remapJar = tasks.withType<RemapJarTask>()
val remapJar = tasks.withType<RemapJarTask>()["remapJar"]
dependsOn(remapJar)
from(remapJar)

configurations = immutableListOf(project.configurations["shade"])
configurations = immutableListOf(shade)
archiveBaseName = rootProject.name
archiveClassifier = implName
isPreserveFileTimestamps = false
Expand All @@ -254,7 +257,7 @@ subprojects {
if (implName in lexForgeImpls) {
manifest {
attributes(
"MixinConfigs" to "zume-${implName}.mixins.json",
"MixinConfigs" to "zume.mixins.json",
)

if (implName in legacyForgeImpls) {
Expand Down Expand Up @@ -304,22 +307,18 @@ unimined.minecraft {
defaultRemapJar = false
}

configurations {
val shade = create("shade")

compileClasspath.get().extendsFrom(shade)
runtimeClasspath.get().extendsFrom(shade)
val shade: Configuration by configurations.creating {
configurations.compileClasspath.get().extendsFrom(this)
configurations.runtimeClasspath.get().extendsFrom(this)
}

dependencies {
"shade"("blue.endless:jankson:${"jankson_version"()}")

compileOnly("org.apache.logging.log4j:log4j-core:${"log4j_version"()}")

compileOnly(project(":stubs"))

implementation(project(":api"))
"shade"(project(":api")) { isTransitive = false }
shade(project(":api")) { isTransitive = false }

uniminedImpls.forEach {
implementation(project(":${it}")) { isTransitive = false }
Expand All @@ -337,24 +336,33 @@ tasks.shadowJar {
mixinPlugin = "dev.nolij.zume.ZumeMixinPlugin"
}

val shadowJar = this
from("LICENSE") {
rename { "${it}_${"mod_id"()}" }
}

exclude("*.xcf")

configurations = immutableListOf(project.configurations["shade"])
configurations = immutableListOf(shade)
archiveClassifier = null
isPreserveFileTimestamps = false
isReproducibleFileOrder = true

uniminedImpls.forEach { impl ->
val remapJars = project(":${impl}").tasks.withType<RemapJarTask>()
shadowJar.dependsOn(remapJars)
remapJars.forEach { remapJar ->
from(zipTree(remapJar.archiveFile.get())) {
exclude("fabric.mod.json", "mcmod.info", "META-INF/mods.toml", "pack.mcmeta")
if(releaseChannel.proguard) {
val tasks = project(":${impl}").tasks.withType<ProGuardTask>()
tasks.forEach { task ->
this.dependsOn(task)
from(zipTree(task.outJarFiles.single() as File)) {
exclude("fabric.mod.json", "mcmod.info", "META-INF/mods.toml", "pack.mcmeta")
}
}
} else {
val tasks = project(":${impl}").tasks.withType<RemapJarTask>()
tasks.forEach { task ->
this.dependsOn(task)
from(task.archiveFile.get().asFile) {
exclude("fabric.mod.json", "mcmod.info", "META-INF/mods.toml", "pack.mcmeta")
}
}
}
}
Expand Down
13 changes: 11 additions & 2 deletions buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,21 @@ fun DependencyHandler.plugin(id: String, version: String) {

dependencies {
implementation("org.ow2.asm:asm-tree:9.7")
implementation("com.google.code.gson:gson:2.10.1")
implementation("com.guardsquare:proguard-gradle:7.4.2")

implementation("org.apache.ant:ant:1.10.13")
plugin(id = "com.github.johnrengelman.shadow", version = "8.1.1")
plugin(id = "xyz.wagyourtail.unimined", version = "1.2.3")
plugin(id = "xyz.wagyourtail.unimined", version = "1.2.4-SNAPSHOT")
plugin(id = "com.github.gmazzo.buildconfig", version = "5.2.0")
plugin(id = "org.ajoberstar.grgit", version = "5.2.2")
plugin(id = "me.modmuss50.mod-publish-plugin", version = "0.4.5")
}

gradlePlugin {
plugins {
create("proguard") {
id = "dev.nolij.zume-proguard"
implementationClass = "dev.nolij.zumegradle.ZumeProGuard"
}
}
}
13 changes: 8 additions & 5 deletions buildSrc/src/main/kotlin/dev/nolij/zumegradle/JarCompressing.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.nolij.zumegradle

import com.google.gson.GsonBuilder
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFile
Expand Down Expand Up @@ -55,16 +56,18 @@ fun squishJar(jar: File, classProcessing: ClassShrinkingType, jsonProcessing: Js

jar.delete()

val gson = GsonBuilder().apply {
if(jsonProcessing == JsonShrinkingType.PRETTY_PRINT) setPrettyPrinting()
}.create()
val json = JsonSlurper()

JarOutputStream(jar.outputStream()).use { out ->
out.setLevel(Deflater.BEST_COMPRESSION)
contents.forEach { var (name, bytes) = it
if (jsonProcessing != JsonShrinkingType.NONE &&
name.endsWith(".json") || name.endsWith(".mcmeta") || name == "mcmod.info") {
bytes = gson.fromJson(String(bytes), Any::class.java).toString().toByteArray()
bytes = when(jsonProcessing) {
JsonShrinkingType.MINIFY -> JsonOutput.toJson(json.parse(bytes)).toByteArray()
JsonShrinkingType.PRETTY_PRINT -> JsonOutput.prettyPrint(JsonOutput.toJson(json.parse(bytes))).toByteArray()
else -> bytes
}
}

if (name.endsWith(".class")) {
Expand Down
Loading
Loading