Gradle Badass-Laufzeit-Plugin und ProGuard Gradle Plugin

8

Wie starte ich Proguard vor jPackage?

Einführung

Ich entwickle eine App in JavaFx mit Gradle-Plugins und packe sie mit jPackager, auch mit den Gradle-Plugins.

Die wichtigsten Plugins, die ich benutze, sind:

id 'org.openjfx.javafxplugin' version '0.0.8'
id 'org.beryx.runtime' version '1.7.0'
id "com.github.johnrengelman.shadow" version "5.1.0"

Meine aktuelle Gradle-Version ist: gradle-5.6.2-all

Problembeschreibung

Wie verwende ich Proguard, damit der Code verschleiert und optimiert wird, bevor jPackage seine Arbeit erledigt?

Ich kann die Proguard-Aufgaben ausführen, aber wenn ich jPackage ausführe, wird der Code nicht verschleiert!

Ich habe ein Tutorial ( Tutorial ) für eine ältere Gradle-Version gefunden, bin mir jedoch nicht sicher, wie ich dies mit den aktuellen Plugins mischen soll. Ich habe ein paar Code-Schnipsel ausprobiert, aber sie konnten nicht alle erstellt werden, und ich möchte dieses Thema nicht mit einer Menge nicht funktionierenden Codes überladen.

Mein aktuell arbeitendes build.gradle

// 1. Include proguard dependency
buildscript {
    repositories {
        jcenter()
        mavenCentral()
    }
    dependencies {
        classpath 'net.sf.proguard:proguard-gradle:6.2.0'
    }
}

plugins {
    id 'java'
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.8'
    id 'org.beryx.runtime' version '1.7.0'
    id "com.github.johnrengelman.shadow" version "5.1.0"

}


dependencies {
    compile "org.controlsfx:controlsfx:11.0.0"
    compile "eu.hansolo:tilesfx:11.13"
    compile "com.jfoenix:jfoenix:9.0.9"
    compile "org.apache.httpcomponents:httpclient:4.5.9"
    compile "org.json:json:20180813"
    compile "mysql:mysql-connector-java:8.0.17"
    compile "org.jasypt:jasypt:1.9.3"
    compile "com.mchange:c3p0:0.9.5.4"
    compile "com.sun.mail:javax.mail:1.6.2"
    compile "commons-validator:commons-validator:1.6"
    compile 'org.openjfx:javafx-base:11:win'
    compile 'org.openjfx:javafx-controls:11:win'
    compile 'org.openjfx:javafx-fxml:11:win'
    compile 'org.openjfx:javafx-graphics:11:win'

}

repositories {
    mavenCentral()
}

javafx {
    version = "13"
    modules = [ 'javafx.controls','javafx.graphics','javafx.fxml'  ]
}

mainClassName = 'Main'

runtime {
    options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']

   jpackage {
        jpackageHome = 'C:/Program Files/Java/openjdk-14-jpackage+1-49_windows-x64_bin/'



        if(org.gradle.internal.os.OperatingSystem.current().windows) {
            installerType = 'msi'
            imageOptions = []
            installerOptions = ['--win-per-user-install',
                '--win-dir-chooser',
                '--win-menu',
                '--win-shortcut',
                '--verbose',
                '--description','Test of proguard with jPackage',
                '--name', 'Test-ProguardJPackage',
                '--vendor','DoesItMatter']
        }
    }

}

compileJava {
    doFirst {
        options.compilerArgs = [
                '--module-path', classpath.asPath,
                 '--add-modules', 'javafx.controls,javafx.fxml'
        ]
    }
}

run {
    doFirst {
        jvmArgs = [
                '--module-path', classpath.asPath,
                 '--add-modules', 'javafx.controls,javafx.fxml'
        ]
    }
}




task cleanClasses(type: Delete) {
    delete "${buildDir}/classes/java/main"
    delete "${buildDir}/resources/java/main"
}

classes.dependsOn(cleanClasses)

// 2.2 Add proguard task
task proguard(type: proguard.gradle.ProGuardTask, dependsOn: classes) {
    injars project.sourceSets.main.output
    outjars "${buildDir}/proguard/output.jar"

    libraryjars project.sourceSets.main.compileClasspath

    configuration 'proguard.conf'
}

// 2.3 Clean after proguard task
task cleanAfterProguard(type: Delete, dependsOn: proguard) {
    delete "${buildDir}/classes/java/main"
    delete "${buildDir}/resources/java/main"
}

// 2.4 Extract output jar to buildDir 
task unpackProguardOutput (type: Copy, dependsOn: cleanAfterProguard) {
    from zipTree("${buildDir}/proguard/output.jar")
    into file("${buildDir}/classes/java/main")
}


// 3. Create a task to run the app with the proguarded buildDir
task runProguard(type: JavaExec, dependsOn: unpackProguardOutput) {
    classpath = sourceSets.main.runtimeClasspath
    jvmArgs = ['--module-path', classpath.asPath,
               '--add-modules', 'javafx.controls,javafx.fxml' ]
    main = 'Main' // <-- this name will depend on the proguard result
}

Verweise

Packen Sie eine nicht modulare JavaFX-Anwendung

JavaFX Proguard-Verschleierung


KenobiShan
quelle

Antworten:

1

Problem

Wenn Sie eine Gradle-Aufgabe ausführen, müssen Sie die zuvor ausgeführten Aufgaben basierend auf ihren Abhängigkeiten berücksichtigen.

In der von Ihnen verknüpften JavaFX Proguard-Verschleierungsantwort können Sie sehen, dass die benutzerdefinierten Proguard-Aufgaben zwischen ihnen verkettet sind. Wenn Sie sie ausführen ./gradlew runProguard, erhalten Sie tatsächlich die folgende Reihenfolge von Aufgaben:

:cleanClasses
:compileJava
:processResources
:classes
:proguard
:cleanAfterProguard
:unpackProguardOutput
:runProguard

Wenn Sie jetzt dort runtimePlugin für Aufgaben wie runtimeoder hinzufügen möchten jpackage, erhalten Sie diese Reihenfolge:

:cleanClasses
:compileJava
:processResources
:classes
:jar
:startScripts
:installDist
:jre
:runtime

Sehen Sie das Problem? Die Proguard-Aufgaben werden überhaupt nicht aufgerufen, da wir die runtimeAufgabe nicht so geändert haben , dass sie von Proguard abhängt.

Lösung

Wie Sie sehen können, die beide runtimeund sind jpackageabhängig von dem Glas des Projekts. Eine einfache Lösung besteht darin, die proguardAufgabe in die jarAufgabe einzubinden. Daher erstellen wir ein Glas aus den proguardierten Klassen anstelle der ursprünglichen.

So etwas in Ihrem Build sollte funktionieren:

jar.dependsOn(unpackProguardOutput)

Es gibt jedoch ein Problem mit den Ressourcen (die gesicherte FXML-Datei wird von der ursprünglichen überschrieben), da die ursprünglichen Ressourcen erneut in das JAR kopiert werden.

So können wir stattdessen die JAR-Aufgabe ändern:

jar {
    dependsOn 'cleanAfterProguard'
    manifest {
        attributes(
                'Main-Class': 'org.openjfx.Launcher'
        )
    }
    from zipTree("${buildDir}/proguard/output.jar")
}

Dies ist jetzt die Aufgabenreihenfolge:

:cleanClasses
:compileJava
:processResources
:classes
:proguard
:cleanAfterProguard
:jar
:startScripts
:installDist
:jre
:runtime

./gradlew clean runtimeWenn Sie jetzt laufen, wird ein Laufzeit-Image basierend auf einem Proguarded generiert hellofx.jar. Laufen build/image/bin/hellofxsollte funktionieren.

Gleiches gilt für jpackage:

:cleanClasses
:compileJava
:processResources
:classes
:proguard
:cleanAfterProguard
:jar
:startScripts
:installDist
:jre
:jpackageImage
:jpackage

In diesem Bild sehen Sie, dass das in der hellofx.app enthaltene Glas nur vorsichtige Klassen enthält.

José Pereda
quelle
Vielen Dank für die Antwort, aber ich denke, meine funktioniert noch nicht, weil Ihre Antwort erfordert, dass Shadowjar dep. Das Jar {} wird also nicht verwendet. [task ': cleanClasses', task ': compileJava', task ': processResources', task ': classes', task ': shadowJar', task ': startShadowScripts', task ': installShadowDist', task ': jre', task ': jpackageImage', Aufgabe ': jpackage']
KenobiShan
1
Warum brauchst du überhaupt das Schatten-Plugin? Sie machen ein Installationsprogramm. Passen Sie den Build an Ihre Bedürfnisse an und entfernen Sie das, was nicht erforderlich ist.
José Pereda
Ich weiß nicht, warum ich das Schatten-Plugin verwendet habe. Ich entfernte und es funktioniert jetzt: github.com/KenobySky/hellofx
KenobiShan
1
Großartig. Besser, wenn Sie die JavaFX-Abhängigkeiten aus dem Build entfernen compileJava, runwird all dies vom JavaFX-Plugin erledigt.
José Pereda
1
Diese:compile “.org.openjfx:...”
José Pereda
0

Siehe Handbuch , der buildscriptBlock, der die Abhängigkeit bereitstellt, sieht ganz anders aus:

buildscript {
    repositories {
        flatDir dirs: '/usr/local/java/proguard/lib'
    }
    dependencies {
        classpath ':proguard:'
    }
}

Während es sich beschwert, dass es ist unable to resolve class proguard.gradle.ProGuardTask, wird es wahrscheinlich keine geben proguard.gradle.ProGuardTask. Und dependsOn: 'obfuscatedJar'ist seltsam, weil die Aufgabe myProguardTaskes verschleiern soll.

task myProguardTask(type: proguard.gradle.ProGuardTask) {
    ...
}

Stellen Sie auch sicher, dass /usr/local/java/proguard/libdas sogar installiert ist, z. mit locate proguard, weil es für Java nicht vom Android SDK bereitgestellt wird - und daher muss es als buildscriptAbhängigkeit bereitgestellt werden . Dann müssen Sie einen benutzerdefinierten Code schreiben proguard.txt, der auf allen Warnungen basiert, die beim Verschleiern ausgegeben werden.


Das Aktualisieren des proguard-gradlePlugins ist möglicherweise eine weitere mögliche Option:

dependencies {
    classpath 'net.sf.proguard:proguard-gradle:6.2.0'
}

Als Referenz wäre dies ProGuardTask.java .

Martin Zeitler
quelle
Sie haben nicht richtig erklärt, wie die Aufgabe für den Javafx-Build geschrieben wird. Beachten Sie auch, dass Jpackage nach dem Build ausgeführt wird. Ihre Antwort ist also unvollständig.
KenobiShan
@ KenobiShanhow soll ich das komplett beantworten, wenn ich keinen Java-Code habe? Wenn die Proguard-Aufgabe hinzugefügt wird, müssen Konfigurationsregeln geschrieben werden, die nur geschrieben werden können, wenn sich Proguard über fehlende Klassen und dergleichen beschwert.
Martin Zeitler
Das build.gradle benötigt keinen "Java-Code". Beachten Sie, dass die Frage die Verwendung von Proguard mit den beteiligten Plugins und mit Proguard betrifft. Die Verwendung von Proguard ist in gängigen Java-Anwendungen trivial. Diese Einschränkungen machen die Leute jedoch neugierig auf diese Frage
KenobiShan