如何使用KotlinJVM(不是Android)和Gradle设置Proguard

pvcm50d1  于 2023-04-21  发布在  Kotlin
关注(0)|答案(2)|浏览(391)

我想问你是否知道一个指南,或者如果你知道如何使用Proguard与Kotlin和Gradle,并希望分享你的知识,我真的很感激。已经搜索了Stack Overflow,但找不到一个关于使用Proguard + Kotlin JVM(不是android!)+ Gradle的问题。
我只在互联网上找到了关于Android的指南,但我没有使用Android的Kotlin,我正在构建Java插件(换句话说,JVM)与Kotlin,我想使用Proguard来缩小和模糊我的代码。(这些依赖项不需要被混淆,但可以被缩小,并且最终需要存在于由Proguard创建的混淆jar中)。
我想知道所有的步骤,比如如何升级Gradle来自动缩小和混淆我的代码(使用自定义任务),如何从Java编译的类中删除Kotlin元数据,常见问题和解决方案,以及任何你认为有用的东西,一切都很有帮助。非常感谢。

eni9jsuy

eni9jsuy1#

我在一段时间前就开始使用了,参考Proguard manual来了解其配置文件的语法。此外,出于某种原因,有时Proguard只是说当前混淆的jar是“最新的”,即使没有jar,这似乎是一个错误,我无法找到重现的步骤。如果发生这种情况,只需更改您正在使用的Proguard版本并重新加载Gradle依赖项。
build.gradle.kts

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

// add this
buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("com.guardsquare:proguard-gradle:7.1.1") {
            exclude("com.android.tools.build")
        }
    }
}

plugins {
    kotlin("jvm") version "1.5.30"
    id("com.github.johnrengelman.shadow") version "7.0.0"
}

group = "com.yourgroup"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
    maven("https://oss.sonatype.org/content/groups/public/")
}

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0")
    // your dependencies here
}

tasks.test {
    useJUnitPlatform()
}

// disables the normal jar task
tasks.jar { enabled = false }

// and enables shadowJar task
artifacts.archives(tasks.shadowJar)

tasks.shadowJar {
    archiveFileName.set(rootProject.name + ".jar")
    val dependencyPackage = "${rootProject.group}.dependencies.${rootProject.name.toLowerCase()}"
    // your relocations here
    exclude("ScopeJVMKt.class")
    exclude("DebugProbesKt.bin")
    exclude("META-INF/**")
}

tasks.register<proguard.gradle.ProGuardTask>("proguard") {
    // here is where you configure your Proguard stuff, you can include libraries directly
    // through here, or in the configuration file, I usually just use the configuration file
    // to do everything (it can be any name and extension you want, just using .pro here cause
    // that's what Android uses)
    configuration("proguard-rules.pro")
}

// keep this if you want run proguard task automatically after building
tasks.build.get().finalizedBy(tasks.getByName("proguard"))

tasks.withType<JavaCompile> {
    sourceCompatibility = "16"
    targetCompatibility = "16"
    options.encoding = "UTF-8"
}

tasks.withType<KotlinCompile> { kotlinOptions.jvmTarget = "16" }

proguard-rules.pro:这只是一个用于minify Minecraft插件的示例文件,但无论您处理的是哪种类型的jar,其逻辑都适用。

# injars = your shadowed jar
-injars  build/libs/YourShadowedJarHere.jar
# outjars = the name of the new obfuscated/minified jar
-outjars build/libs/YourShadowedJarHere-min.jar

# important! you need to add this "rt" file from your JDK as libraryjars!
-libraryjars "C:\Program Files\Java\jdk1.8.0_291\jre\lib\rt.jar"
# add here the jar to any compileOnly dependency you might have (or add "dontwarn" to make proguard ignore the missing classes)
-libraryjars "PathTo\YourProject\SomeLocalLibraries\SomeLocalLibrary.jar"

-dontwarn net.minecraft.**
-dontwarn org.bukkit.**
-dontwarn com.google.**
-dontwarn com.comphenix.**
-dontwarn android.**
-dontwarn org.hibernate.**
-dontwarn com.sk89q.worldedit**
-dontwarn com.sk89q.worldguard**
-dontwarn net.milkbowl.vault.economy**
-keep class yourpackage.dependencies.yourproject.hikari.metrics.**
-dontwarn com.codahale.metrics.**
-keep class com.codahale.metrics.**
-dontwarn **hikari.metrics**
-dontwarn javax.crypto.**
-dontwarn javassist.**
-dontwarn **slf4j**
-dontwarn io.micrometer.core.instrument.MeterRegistry
-dontwarn org.codehaus.mojo.**
-dontwarn **prometheus**
-dontwarn **configurate.**
-dontwarn **koin.core.time.**
-dontwarn net.Indyuce.**
-dontwarn **xseries.**
-keepnames class kotlin.coroutines.** { *; }
-dontwarn **kotlinx.coroutines.**
-dontwarn **org.apache.commons.codec**

#-dontshrink
#-dontobfuscate
#-dontoptimize

# Keep your main class
-keep,allowobfuscation,allowoptimization class * extends org.bukkit.plugin.java.JavaPlugin { *; }

# Keep event handlers
-keep,allowobfuscation,allowoptimization class * extends org.bukkit.event.Listener {
    @org.bukkit.event.EventHandler <methods>;
}

# Keep main package name
// -keeppackagenames "your.package"

# Keep public enum names
-keepclassmembers public enum yourpackage.** {
    <fields>;
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

# Keep all ProtocolLib packet listeners (this was rough to get working, don't turn on optimization, it ALWAYS breaks the sensible ProtocolLib)
-keepclassmembers class yourpackage.yourproject.**  {
    void onPacketSending(com.comphenix.protocol.events.PacketEvent);
    void onPacketReceiving(com.comphenix.protocol.events.PacketEvent);
}

# Keep static fields in custom Events
-keepclassmembers,allowoptimization class yourpackage.yourproject.** extends org.bukkit.event.Event {
    @yourpackage.dependencies.kotlin.jvm.JvmStatic <fields>;
    public static final <fields>;
    @yourpackage.dependencies.kotlin.jvm.JvmStatic <methods>;
    public static <methods>;
}

# Remove dependencies obsfuscation to remove bugs factor
#-keep,allowshrinking class yourpackage.dependencies.** { *; }

# If your goal is obfuscating and making things harder to read, repackage your classes with this rule
-repackageclasses yourpackage.yourproject
-allowaccessmodification
-mergeinterfacesaggressively
# You can parse any resource files that might contain a reference of your classes here (so they are updated according to the modifications made by Proguard)
-adaptresourcefilecontents **.yml,META-INF/MANIFEST.MF

# Some attributes that you'll need to keep (warning: removing *Annotation* might break some stuff)
-keepattributes Exceptions,Signature,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
#-keepattributes Exceptions,Signature,Deprecated,LineNumberTable,*Annotation*,EnclosingMethod
#-keepattributes LocalVariableTable,LocalVariableTypeTable,Exceptions,InnerClasses,Signature,Deprecated,LineNumberTable,*Annotation*,EnclosingMethod
qfe3c7zg

qfe3c7zg2#

https://github.com/Guardsquare/proguard/releases提供样本。
Kotlin应用

import proguard.gradle.ProGuardTask

buildscript {
    repositories {
        mavenLocal()
        mavenCentral()
        google()
    }
    dependencies {
        classpath 'com.guardsquare:proguard-gradle:7.3.1'
    }
}

plugins {
    id 'org.jetbrains.kotlin.jvm' version '1.8.0'
    id 'application'
}

group = 'org.example'
version = '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.jetbrains.kotlin:kotlin-test'
}

test {
    useJUnitPlatform()
}

compileKotlin {
    kotlinOptions.jvmTarget = '1.8'
}

compileTestKotlin {
    kotlinOptions.jvmTarget = '1.8'
}

application {
    mainClassName = 'AppKt'
}

ext.baseCoordinates = "${project.name}-${project.version}"

tasks.register('proguard', ProGuardTask) {
    configuration file('proguard.pro')

    injars(tasks.named('jar', Jar).flatMap { it.archiveFile })

    // Automatically handle the Java version of this build.
    if (System.getProperty('java.version').startsWith('1.')) {
        // Before Java 9, the runtime classes were packaged in a single jar file.
        libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
    } else {
        // As of Java 9, the runtime classes are packaged in modular jmod files.
        libraryjars "${System.getProperty('java.home')}/jmods/java.base.jmod", jarfilter: '!**.jar', filter: '!module-info.class'
        //libraryjars "${System.getProperty('java.home')}/jmods/....."
    }

    // This will include the Kotlin library jars
    libraryjars sourceSets.main.compileClasspath

    verbose

    outjars(layout.buildDirectory.file("libs/${baseCoordinates}-minified.jar"))
}

KotlinKts

buildscript {
    repositories {
        mavenCentral()
        google()
    }
    dependencies {
        classpath("com.guardsquare:proguard-gradle:7.3.0")
    }
}

plugins {
    java
    application
}

repositories {
    mavenCentral()
}

dependencies {
    testImplementation("junit:junit:4.12")
}

application {
    mainClassName = "gradlekotlindsl.App"
}

tasks.withType<Jar> {
    manifest {
        attributes["Main-Class"] = application.mainClassName
    }
}

tasks.register<proguard.gradle.ProGuardTask>("proguard") {
    verbose()

    // Alternatively put your config in a separate file
    // configuration("config.pro")

    // Use the jar task output as a input jar. This will automatically add the necessary task dependency.
    injars(tasks.named("jar"))

    outjars("build/proguard-obfuscated.jar")

    val javaHome = System.getProperty("java.home")
    // Automatically handle the Java version of this build.
    if (System.getProperty("java.version").startsWith("1.")) {
        // Before Java 9, the runtime classes were packaged in a single jar file.
        libraryjars("$javaHome/lib/rt.jar")
    } else {
        // As of Java 9, the runtime classes are packaged in modular jmod files.
        libraryjars(
            // filters must be specified first, as a map
            mapOf("jarfilter" to "!**.jar",
                  "filter"    to "!module-info.class"),
            "$javaHome/jmods/java.base.jmod"
        )
    }

    allowaccessmodification()

    repackageclasses("")

    printmapping("build/proguard-mapping.txt")

    keep("""class gradlekotlindsl.App {
                public static void main(java.lang.String[]);
            }
    """)
}

相关问题