Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gradle badass-runtime-plugin and ProGuard Gradle Plugin

How to run proguard before jPackage?

Introduction

Im developing an app in JavaFx using gradle plugins and packaging it with jPackager, also using the gradle plugins.

The main plugins im using are:

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"

My current gradle version is: gradle-5.6.2-all

Problem description

How do I use proguard so the code gets obfuscated and optimized before jPackage do its job?

I can run the proguard tasks, but when I run jPackage, the code doesnt get obfuscated!

Ive found a tutorial (Tutorial) for an older gradle version however im not sure how to mix this with the current plugins. I've tried a few code snippets but they all failed to build and I dont want to clutter this topic with a bunch of non-working code.

My current working 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
}

References

Package a non-modular JavaFX application

JavaFX Proguard Obfuscation


like image 689
KenobiBastila Avatar asked Oct 11 '19 15:10

KenobiBastila


1 Answers

Problem

When you run a Gradle task, you have to take into account the tasks that will be previously executed, based on their dependencies.

In the JavaFX Proguard Obfuscation answer you have linked, you can see that the proguard custom tasks are concatenated between them, and when you run ./gradlew runProguard, actually you get this order of tasks:

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

If you want to add now there runtime plugin, for tasks like runtime or jpackage, you will get this order:

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

Do you see the problem? There is no call at all to the proguard tasks, because we haven't modified the runtime task to depend on proguard.

Solution

As you can see, both runtime and jpackage depend on the jar of the project. So one easy fix will be hooking up the proguard task into the jar task, so we create a jar out of the proguarded classes instead of the original ones.

Something like this in your build should work:

jar.dependsOn(unpackProguardOutput)

However there is an issue with the resources (the proguarded FXML file will be overwritten by the original one), because the original resources are copied again to the jar.

So we can modify the jar task instead:

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

This will be the task order now:

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

Now running ./gradlew clean runtime will generate a runtime image based on a proguarded hellofx.jar. Running build/image/bin/hellofx should work.

The same applies to jpackage:

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

In this pic, you see that the jar included in the hellofx.app contains proguarded classes only.

like image 106
José Pereda Avatar answered Oct 23 '22 11:10

José Pereda