Gradle badass-runtime-plugin y ProGuard Gradle Plugin

8

¿Cómo ejecutar proguard antes de jPackage?

Introducción

Estoy desarrollando una aplicación en JavaFx usando complementos de gradle y empaquetándola con jPackager, también usando los complementos de gradle.

Los principales complementos que estoy usando son:

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"

Mi versión actual de gradle es: gradle-5.6.2-all

Descripción del problema

¿Cómo uso Proguard para que el código se ofusque y optimice antes de que jPackage haga su trabajo?

Puedo ejecutar las tareas de protección, pero cuando ejecuto jPackage, ¡el código no se ofusca!

Encontré un tutorial ( Tutorial ) para una versión anterior de gradle, sin embargo, no estoy seguro de cómo mezclar esto con los complementos actuales. He intentado algunos fragmentos de código pero todos fallaron al compilar y no quiero saturar este tema con un montón de código que no funciona.

Mi trabajo actual 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
}

Referencias

Empaquete una aplicación JavaFX no modular

Ofuscación de JavaFX Proguard


KenobiShan
fuente

Respuestas:

1

Problema

Cuando ejecuta una tarea de Gradle, debe tener en cuenta las tareas que se ejecutarán previamente, en función de sus dependencias.

En la respuesta de Ofuscación de protección de JavaFX que ha vinculado, puede ver que las tareas personalizadas de protección están concatenadas entre ellas, y cuando ejecuta ./gradlew runProguard, realmente obtiene este orden de tareas:

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

Si desea agregar ahora el runtimecomplemento, para tareas como runtimeo jpackage, obtendrá este orden:

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

¿Ves el problema? No hay ninguna llamada a las tareas de protección, porque no hemos modificado la runtimetarea para depender de la protección.

Solución

Como se puede ver, tanto runtimey jpackagedependerá de la jarra del proyecto. Entonces, una solución fácil será conectar la proguardtarea a la jartarea, por lo que creamos un frasco a partir de las clases protegidas en lugar de las originales.

Algo como esto en su compilación debería funcionar:

jar.dependsOn(unpackProguardOutput)

Sin embargo, hay un problema con los recursos (el archivo FXML protegido se sobrescribirá con el original), porque los recursos originales se copian nuevamente en el archivo jar.

Entonces podemos modificar la tarea jar en su lugar:

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

Este será el orden de tareas ahora:

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

Ahora en ejecución ./gradlew clean runtimegenerará una imagen de tiempo de ejecución basada en un programado hellofx.jar. Correr build/image/bin/hellofxdebería funcionar.

Lo mismo se aplica a jpackage:

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

En esta imagen, verá que el jar incluido en hellofx.app contiene solo clases protegidas.

José Pereda
fuente
Gracias por la respuesta, sin embargo, creo que la mía aún no está funcionando porque su respuesta requiere que el dep de shadowjar. Entonces el Jar {} no se usa. [task ': cleanClasses', task ': compileJava', task ': processResources', task ': classes', task ': shadowJar', task ': startShadowScripts', task ': installShadowDist', task ': jre', task ': jpackageImage', tarea ': jpackage']
KenobiShan
1
¿Por qué necesitas el complemento de sombra en primer lugar? Estás haciendo un instalador. Adapte la compilación a sus necesidades y elimine lo que no es necesario.
José Pereda
No sé por qué estaba usando el complemento de sombra. Eliminé
KenobiShan
1
Excelente. Mejor si elimina compileJava, runy las dependencias JavaFX de la compilación, todo eso se ocupa del complemento JavaFX.
José Pereda
1
Estos:compile “.org.openjfx:...”
José Pereda
0

Consulte el manual , el buildscriptbloque que proporciona la dependencia se ve completamente diferente:

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

Si bien se queja, es cierto, es unable to resolve class proguard.gradle.ProGuardTaskprobable que no haya ninguno proguard.gradle.ProGuardTask. Y dependsOn: 'obfuscatedJar'es extraño, porque myProguardTaskse supone que la tarea lo ofusca.

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

También asegúrese de que /usr/local/java/proguard/libesté instalado, por ejemplo. con locate proguard, porque para Java no lo proporciona el SDK de Android, por lo que hay que proporcionarlo como buildscriptdependencia. Luego tendrá que escribir una costumbre proguard.txt, basada en todas las advertencias que arroja cuando se ofusca.


La actualización del proguard-gradlecomplemento podría ser otra opción posible:

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

Como referencia, sería ProGuardTask.java .

Martin Zeitler
fuente
No explicó correctamente cómo escribir la tarea para la compilación javafx. También tenga en cuenta que Jpackage se ejecuta después de la compilación. Entonces tu respuesta es incompleta.
KenobiShan
@KenobiShanhow ¿Debo responder esto completamente, cuando no tenga el código Java? Cuando se agrega la tarea proguard, esto requerirá escribir reglas de configuración, que solo se pueden escribir cuando proguard se queja de clases perdidas y similares.
Martin Zeitler
El build.gradle no requiere el "código java". Tenga en cuenta que la pregunta se refiere al uso de proguard con los complementos involucrados y con proguard involucrado. El uso de Proguard es trivial en aplicaciones java común, sin embargo, esas restricciones es qué está haciendo la gente curiosa acerca de esta cuestión
KenobiShan