Gradle badass-runtime-plugin 和 ProGuard Gradle 插件

Posted

技术标签:

【中文标题】Gradle badass-runtime-plugin 和 ProGuard Gradle 插件【英文标题】:Gradle badass-runtime-plugin and ProGuard Gradle Plugin 【发布时间】:2020-02-09 04:16:57 【问题描述】:

如何在jPackage之前运行proguard?

简介

我正在使用 gradle 插件在 JavaFx 中开发一个应用程序,并使用 jPackager 打包它,也使用 gradle 插件。

我使用的主要插件有:

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"

我当前的 gradle 版本是:gradle-5.6.2-all

问题描述

如何使用 proguard,以便在 jPackage 完成工作之前对代码进行混淆和优化?

我可以运行 proguard 任务,但是当我运行 jPackage 时,代码不会被混淆!

我找到了旧 gradle 版本的教程 (Tutorial),但我不确定如何将它与当前插件混合使用。我已经尝试了一些代码 sn-ps,但它们都未能构建,我不想用一堆不工作的代码来混淆这个主题。

我当前的工作 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


参考文献

Package a non-modular JavaFX application

JavaFX Proguard Obfuscation


【问题讨论】:

【参考方案1】:

问题

当您运行 Gradle 任务时,您必须根据它们的依赖关系考虑之前将执行的任务。

在您链接的JavaFX Proguard Obfuscation 答案中,您可以看到proguard 自定义任务在它们之间连接,当您运行./gradlew runProguard 时,实际上您会得到以下任务顺序:

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

如果你想现在添加runtime 插件,对于像runtimejpackage 这样的任务,你会得到这个命令:

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

你看到问题了吗?根本没有调用 proguard 任务,因为我们没有修改 runtime 任务以依赖 proguard。

解决方案

如您所见,runtimejpackage 都依赖于项目的 jar。因此,一个简单的解决方法是将proguard 任务连接到jar 任务中,因此我们使用经过保护的类而不是原始类创建一个jar。

在你的构建中这样的东西应该可以工作:

jar.dependsOn(unpackProguardOutput)

但是资源存在问题(经过保护的 FXML 文件将被原始文件覆盖),因为原始资源被再次复制到 jar 中。

所以我们可以改为修改jar任务:

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

这将是现在的任务顺序:

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

现在运行 ./gradlew clean runtime 将根据经过保护的 hellofx.jar 生成运行时映像。运行 build/image/bin/hellofx 应该可以工作。

同样适用于jpackage:

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

在这张图片中,您会看到 hellofx.app 中包含的 jar 仅包含经过保护的类。

【讨论】:

感谢您的回答,但是,我认为我的还没有工作,因为您的回答需要 shadowjar dep。所以不使用 Jar 。 [任务':cleanClasses',任务':compileJava',任务':processResources',任务':classes',任务':shadowJar',任务':startShadowScripts',任务':installShadowDist',任务':jre',任务':jpackageImage', 任务':jpackage'] 为什么首先需要影子插件?你正在做一个安装程序。根据您的需要调整构建并删除不必要的内容。 我不知道我为什么要使用影子插件。我删除了它现在可以工作了:github.com/KenobySky/hellofx 太棒了。如果您从构建中删除 compileJavarun 和 JavaFX 依赖项会更好,所有这些都由 JavaFX 插件处理。 这些:compile “.org.openjfx:...”【参考方案2】:

查看manual,提供依赖的buildscript 块看起来完全不同:

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

虽然它抱怨它是unable to resolve class proguard.gradle.ProGuardTask,但很可能不会有任何proguard.gradle.ProGuardTask。而dependsOn: 'obfuscatedJar' 很奇怪,因为任务myProguardTask 应该对其进行混淆处理。

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

还要确保/usr/local/java/proguard/lib 已安装,例如。使用locate proguard,因为对于Java,它不是由android SDK 提供的——因此必须将其作为buildscript 依赖项提供。然后你必须编写一个自定义的proguard.txt,基于它在混淆时抛出的所有警告。


更新proguard-gradle 插件可能是另一种可能的选择:

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

作为参考,这是ProGuardTask.java。

【讨论】:

您没有正确解释如何编写 javafx 构建的任务。另请注意,Jpackage 在构建之后运行。所以你的答案不完整。 @KenobiShanhow 如果没有 Java 代码,我应该完全回答这个问题吗?添加proguard任务时,需要编写配置规则,只能在proguard抱怨缺少类等情况下编写。 build.gradle 不需要“java 代码”。请注意,问题是关于将 proguard 与涉及的插件和涉及的 proguard 一起使用。 proguard 的使用在常见的 java 应用程序中是微不足道的,但是这些限制是人们对这个问题感到好奇的原因

以上是关于Gradle badass-runtime-plugin 和 ProGuard Gradle 插件的主要内容,如果未能解决你的问题,请参考以下文章

GroovyGradle 环境搭建 ( 下载 Gradle 工具 | 查找本地缓存的 Gradle 工具 | 配置 Gradle 环境变量 )

Android Gradle 插件Gradle 构建工具简介 ① ( Gradle 环境配置 | 官网下载 Gradle 软件包 | 在本地用户目录下查找 | 配置 Gradle 环境变量 )

Android Gradle 插件Gradle 依赖管理 ① ( org.gradle.api.Project 配置 | Android Gradle 插件配置与 Gradle 配置关联 ) ★

gradle wrapper, gradle ,gradle plugin 之间的关系

Gradle与Gradle插件

Android Gradle 插件Gradle 自动化构建 ① ( Gradle 构建工具简介 | Gradle 构建工具用途 )