2014-10-20 47 views
28

我已经编写了一个简单的kotlin源文件以便开始使用,并且还有一个gradle脚本文件。 但我不知道如何将主func添加到清单,以便该jar可以自我执行。用Gradle和Kotlin构建一个可自行执行的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' 
    } 
} 

这里是我的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") 
} 

当我启动从终端的jar(Java的罐子MYJar.jar)我得到了下面的堆栈跟踪,告诉我kotlin反射库类缺失,并且确实没有添加到jar中。似乎我错过了最后一个罐子里的kotlin编译器工件类,还有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 

我使用科特林0.9.66和gradle这个2.1

+0

请注意,Kotlin为诸如'main'等顶级函数生成的类名是在同一个文件中定义的包,以及附加了'KT'的文件名。在你的情况下,这将是'com.loloof64.kotlin.exps.MultideclarationsKT'。您可以通过在文件顶部添加'@file:JvmName(“OtherName”)'来为文件中的所有顶级函数定义一个新的类名,从而改变这种行为。 – 2015-12-31 00:57:42

回答

16

我已经找到了解决方法(感谢MkYong website

  1. 的gradle这个脚本需要科特林编译神器作为一个依赖
  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) } } 
} 
+3

对我来说它没有编译器的依赖关系,收集这个jar文件就足够了 – 2015-03-16 23:56:50

+0

可以确认编译器依赖关系是不需要的,收集文件就够了。 – JustACluelessNewbie 2016-05-02 19:41:36

+0

执行任务后,jar在哪里? – Franmcod 2017-11-22 12:44:15

24

添加插件application,然后设置mainClassName

mainClassName = '[your_namespace].[your_arctifact]Kt' 

例如,假设你已经把下面的代码一个名为main.kt的文件:

package net.mydomain.kotlinlearn 

import kotlin 
import java.util.ArrayList 

fun main(args: Array<String>) { 

    println("Hello!") 

} 

build.gradle应该是:

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

mainClassName = "net.mydomain.kotlinlearn.MainKt" 

事实上科特林正在建立一个类来封装你与你的文件同名命名的主要功能 - 与标题案例。

+1

您是否可以更新您对Kotlin为顶层功能创建类的新命名约定的回答。在他的例子中,现在是:'com.loloof64.kotlin.exps.MultideclarationsKT'作为类名。对于Kotlin 1.0测试版和更高版本而言,情况确实如此。 – 2015-12-31 00:56:08

+0

已更新为Kotlin 1.0 Beta及更新版本。谢谢Jayson。 – Guildenstern70 2016-01-04 15:01:32

+1

这不应该被接受的答案;它是正确的,但不是完整的图片:它需要'收集'Kotlin运行时文件来创建一个完整的可执行文件jar,如下面的@ loloof64例子。 – 2017-04-21 02:42:06

0

如果你碰巧是愚蠢的,像我这样的:

不要创建您的IntelliJ运行配置为应用程序。 IntelliJ会认为它是永不工作的Java &。相反,请使用“Kotlin”条目。

相关问题