使用Gradle和Kotlin构建一个可自我执行的jar

lol*_*f64 43 gradle kotlin

我已经编写了一个简单的kotlin源文件以便开始使用,还有一个gradle脚本文件.但我无法弄清楚如何将主要功能添加到清单中,以便jar可以自行执行.

这是我的build.gradle脚本:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:0.9.66'
    }
}
apply plugin: "kotlin"
repositories {
    mavenCentral()
}
dependencies {
    compile 'org.jetbrains.kotlin:kotlin-stdlib:0.9.66'
}

jar {
    manifest {
        attributes 'Main-Class': 'com.loloof64.kotlin.exps.ExpsPackage'
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的com.loloof64.kotlin.exps.Multideclarations.kt

package com.loloof64.kotlin.exps

class Person(val firstName: String, val lastName: String) {
    fun component1(): String {
        return firstName
    }
    fun component2(): String {
        return lastName
    }
}

fun main(args: Array < String > ) {
    val(first, last) = Person("Laurent", "Bernabé")
    println("First name : $first - Last name : $last")
}
Run Code Online (Sandbox Code Playgroud)

当我从终端(java -jar MYJar.jar)启动jar时,我得到以下stacktrace,告诉我kotlin反射库类缺失,实际上它们还没有被添加到jar中.似乎我错过了最终jar中的kotlin-compiler工件类,以及kotlin-stdlib源代码,但我不知道如何调整gradle构建.

$> java -jar build/libs/kotlin_exps.jar 

Exception in thread "main" java.lang.NoClassDefFoundError: kotlin/reflect/jvm/internal/InternalPackage
    at com.loloof64.kotlin.exps.ExpsPackage.<clinit>(MultiDeclarations.kt)
Caused by: java.lang.ClassNotFoundException: kotlin.reflect.jvm.internal.InternalPackage
    at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 1 more
Run Code Online (Sandbox Code Playgroud)

我正在使用Kotlin 0.9.66和gradle 2.1

Gui*_*n70 33

添加插件application,然后设置mainClassName

mainClassName = '[your_namespace].[your_arctifact]Kt'
Run Code Online (Sandbox Code Playgroud)

例如,假设您已将以下代码放在名为的文件中main.kt:

package net.mydomain.kotlinlearn

import kotlin
import java.util.ArrayList

fun main(args: Array<String>) {

    println("Hello!")

}
Run Code Online (Sandbox Code Playgroud)

你的build.gradle应该是:

apply plugin: 'kotlin'
apply plugin: 'application'

mainClassName = "net.mydomain.kotlinlearn.MainKt"
Run Code Online (Sandbox Code Playgroud)

事实上,Kotlin正在构建一个类来封装您的主要函数,该函数使用与文件相同的名称命名 - 使用Title Case.

  • 这不应该是公认的答案; 这是正确的,但不是完整的图片:需要"收集"Kotlin运行时文件来制作一个完整的可执行jar,如下面@ loloof64的例子. (2认同)

lol*_*f64 25

我找到了解决方法(感谢MkYong网站)

  1. gradle脚本需要kotlin-compiler工件作为依赖项
  2. gradle脚本需要一种方法来收集所有kotlin文件并将它们放入jar中.

所以我得到以下gradle脚本:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
       classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.0.1-2'
    }
}

apply plugin: "kotlin"

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.jetbrains.kotlin:kotlin-stdlib:1.0.1-2'
}

jar {
    manifest {
        attributes 'Main-Class': 'com.loloof64.kotlin.exps.MultideclarationsKT'
    }

    // NEW LINE HERE !!!
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
Run Code Online (Sandbox Code Playgroud)

  • 对我来说它没有编译器依赖,但收集jar文件就足够了 (3认同)

the*_*e64 14

在构建 Artifact 时,上述解决方案都不适合我。

IDE 版本IntelliJ IDEA 2019.1.1

要解决此问题,请执行以下操作

脚步

第 1 步 - 创建工件

  1. 转到文件 -> 项目结构 -> 工件

  2. 单击+-> JAR->From modules with dependencies

在此处输入图片说明

  1. 选择你的程序 Main Class

在此处输入图片说明

第 2 步 - 更改清单路径

  1. 将 的值更改Directory for META-INF/MANIFEST.MF为您的项目根目录。

    例如,从 /your/project/directory/src/main/kotlin/your/project/directory

在此处输入图片说明

  1. OK,然后按ApplyOK

第 3 步 - 构建工件

  1. 最后,转到Build-> Build Artifacts-> [your-artifact-name]-> Build

生成的JAR文件可以在out/artifact/[your-artifact-name]目录中找到。(y)

  • 非常感谢!!!经过多次尝试,这是唯一对我有用的方法! (2认同)