如何使用Gradle从可执行的jar文件中创建可执行文件?

时间:2020-07-23 20:54:05

标签: java gradle

我正在为我的应用程序(python编译器)使用gradle。我以前已经用C ++写过一篇文章,但是我想在Java方面做得更好,因为我对Java有更多的了解。我正在使用gradle构建。到目前为止,这是我的项目的样子:

.
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
    ├── main
    │   ├── java
    │   │   └── compiler
    │   │       ├── Lexer.java
    │   │       ├── Main.java
    │   │       └── TableEntry.java
    │   └── resources
    └── test
        ├── java
        │   └── compiler
        │       └── MainTest.java
        └── resources

LexerTableEntry文件并不重要。这是我的build.gradle文件的样子:

repositories {
    mavenCentral()
}

apply plugin: 'java'

version '0.1.0'

sourceCompatibility = '1.8'
targetCompatibility = '1.8'

jar {
    manifest {
        attributes 'Implementation-Title': 'python',
        'Implementation-Version': version, 
        'Main-Class': 'compiler.Main'
    }
}

dependencies {
    implementation 'com.google.guava:guava:29.0-jre'

    testImplementation 'junit:junit:4.13'
}

task deleteBin(type: Delete) {
    doLast {
        new File('bin').deleteDir()
    }
}

tasks.clean.dependsOn(tasks.deleteBin)

tasks.jar.doLast {
    copy {
        from 'build/libs'
        into 'bin'
    }
}

这应该做的是将Main.java文件构建到可执行jar中,然后将其复制到名为bin的目录中。它做什么。在我叫./gradlew build之后,这是树的样子:

.
├── bin
│   └── python-0.1.0.jar
├── build
│   ├── classes
│   │   └── java
│   │       ├── main
│   │       │   └── compiler
│   │       │       ├── Lexer.class
│   │       │       ├── Main.class
│   │       │       └── TableEntry.class
│   │       └── test
│   │           └── compiler
│   │               └── MainTest.class
│   ├── generated
│   │   └── sources
│   │       ├── annotationProcessor
│   │       │   └── java
│   │       │       ├── main
│   │       │       └── test
│   │       └── headers
│   │           └── java
│   │               ├── main
│   │               └── test
│   ├── libs
│   │   └── python-0.1.0.jar
│   ├── reports
│   │   └── tests
│   │       └── test
│   │           ├── css
│   │           │   ├── base-style.css
│   │           │   └── style.css
│   │           ├── index.html
│   │           └── js
│   │               └── report.js
│   ├── test-results
│   │   └── test
│   │       └── binary
│   │           ├── output.bin
│   │           ├── output.bin.idx
│   │           └── results.bin
│   └── tmp
│       ├── compileJava
│       │   └── source-classes-mapping.txt
│       ├── compileTestJava
│       │   └── source-classes-mapping.txt
│       └── jar
│           └── MANIFEST.MF
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
    ├── main
    │   ├── java
    │   │   └── compiler
    │   │       ├── Lexer.java
    │   │       ├── Main.java
    │   │       └── TableEntry.java
    │   └── resources
    └── test
        ├── java
        │   └── compiler
        │       └── MainTest.java
        └── resources

但是我当时认为使用我的编译器的人需要安装Java才能真正使用它。在C ++中,它已经将其编译为可执行文件,这很方便。经过一番研究,我发现了一个名为launch4j的插件,但似乎无法正常工作。我还需要哪些其他选项将jar文件转换为可执行文件?

很抱歉,没有解释为什么launch4j无法正常工作。所以我去了github repository,它说要添加此插件:

'edu.sc.seis.launch4j'

我添加了它,而gradle却不认识。我输入的行:

apply plugin: 'edu.sc.seis.launch4j'

输出:

Plugin with id 'edu.sc.seis.launch4j' not found.

因此,我去了maven中央存储库搜索,并再次发现它是对here的依赖。当我将这一行添加到我的dependencies部分时,它变得很好:

implementation 'edu.sc.seis.gradle:launch4j:1.0.6'

但是,当我尝试像这样编辑launch4j任务时:

launch4j {
}

它说找不到该任务。

Could not find method launch4j() for arguments [build_c92xwmoykapsewu0cy351y5ww$_run_closure4@5635a004] on root project 'python' of type org.gradle.api.Project.

1 个答案:

答案 0 :(得分:1)

launch4j很好。奇怪的是,您找到了一个精确描述所需内容的工具,而您所要说的就是:“ ...它不起作用”。

一些注意事项可以帮助您使用launch4j:

  • 这当然仅适用于Windows。
  • 您仍然需要交付整个VM。它永远不会是一个可执行文件。 Java不是那种工具。
  • 您需要一个将exe(由launch4j制造)+ VM +所有dep放置在单个位置的安装程序。

您最终会得到类似的东西:

C:\Program Files\MyApp\myapp.exe
C:\Program Files\MyApp\jvm\(a bunch of files here; an entire JRE/JDK installation)
C:\Program Files\MyApp\lib\dep1.jar
C:\Program Files\MyApp\lib\dep2.jar

依赖关系当然是可选的,也可以划分。

然后您可以告诉launch4j使用该VM,而不要使用任何已安装的VM(如果有)。这还具有与在桌面上运行Java应用程序的当前“模型”兼容的便利副作用(这是您(应用程序供应商)负责VM分发,而不是oracle +最终用户,这是它的方式或多或少都可以使用到java8(已过时)为止,而且您还可以确切知道要在哪个版本上运行。

从Java 11开始,您可以使用jlink制作“摇晃的”自定义VM:这些包含您最终最终使用的VM的位数。您确实需要切换到模块化构建(这涉及制作module-info.java文件-如果您确实想走这条路,可以找到很多教程)。

我不知道您是否可以使这些像树一样的VM与launch4j一起工作,但是您应该能够。

我不知道针对Linux和Mac的任何解决方案。

相关问题