web-dev-qa-db-ja.com

GradleとKotlinを使用して自己実行可能jarを構築する

始めるために簡単なkotlinソースファイルとgradleスクリプトファイルを書きました。しかし、メインのfuncをマニフェストに追加する方法がわからないため、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")
}

ターミナル(Java -jar MYJar.jar)からjarを起動すると、次のスタックトレースが表示されます。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

Kotlin 0.9.66とgradle 2.1を使用しています

42
loloof64

回避策を見つけました( MkYong website に感謝)

  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) } }
}
25
loloof64

プラグイン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"

実際、Kotlinは、ファイルの同じ名前で名前を付けたメイン関数をカプセル化するクラスを作成しています-タイトルケースを使用します。

33
Guildenstern70

Artifactの構築中に、上記のソリューションはどれも役に立ちませんでした。

IDEバージョンIntelliJ IDEA 2019.1.1

この問題を修正するには、次を実行します

手順

ステップ1-アーティファクトの作成

  1. File-> Project Structure-> Artifactsに移動します

  2. +-> JAR-> From modules with dependenciesをクリックします

enter image description here

  1. プログラムのMain Classを選択します

enter image description here

ステップ2-マニフェストパスの変更

  1. Directory for META-INF/MANIFEST.MFの値をプロジェクトルートに変更します。

    たとえば、/your/project/directory/src/main/kotlinから/your/project/directoryまで

enter image description here

  1. OKを押してから、ApplyおよびOKを押します。

ステップ3-アーティファクトのビルド

  1. 最後に、Build-> Build Artifacts-> [your-artifact-name]-> Build。に移動します。

生成されたJARファイルは、out/artifact/[your-artifact-name]ディレクトリにあります。 (y)

2
theapache64

おかげで、私にとってはjarセクションを追加するのに役立ちました

jar {
    manifest {
        attributes 'Main-Class': 'com.photofiles.Application'
    }

    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}

アプリケーションプラグインは必要ありません。

1
paucls

私のようにたまたま馬鹿になった場合:

IntelliJ実行構成をアプリケーションとして作成しないでください。 IntelliJは、それがJavaであると仮定し、それは機能しません。代わりに、「Kotlin」エントリを使用します。

0
Tim Keating

GradleKotlinDSLを使用する場合、私の duplicate の質問には次の答えがあります。

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar

plugins {
    kotlin("jvm") version "1.2.51"
    id("com.github.johnrengelman.shadow") version "2.0.4"
}

group = "xxx.yyy"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    implementation(kotlin("stdlib-jdk8"))
}

tasks.withType<KotlinCompile> {
    kotlinOptions.jvmTarget = "1.8"
}

tasks.withType<ShadowJar> {

    manifest.attributes.apply {
        put("Implementation-Title", "Gradle Jar File Example")
        //put("Implementation-Version" version)
        put("Main-Class", "HelloKotlinWorld.App")
    }

これが最も簡単な解決策だと思います。ああ、おそらくKotlinではなくDSLだけを使用しているのでしょう。

0
Thufir