Gradleを使用して依存関係のあるjarをビルドする


122

マルチプロジェクトビルドがあり、サブプロジェクトの1つにファットjarをビルドするタスクを入れました。クックブックに記載されているタスクと同様のタスクを作成しました。

jar {
  from configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
  manifest { attributes 'Main-Class': 'com.benmccann.gradle.test.WebServer' }
}

これを実行すると、次のエラーが発生します。

原因:未解決の状態でない構成は変更できません!

このエラーの意味がわかりません。バグの場合に備えて、Gradle JIRAでもこれを報告しました

回答:


195

更新:新しいGradleバージョン(4+)では、compile修飾子は廃止され、新しいapiimplementation構成が優先されます。これらを使用する場合、以下が機能するはずです。

// Include dependent libraries in archive.
mainClassName = "com.company.application.Main"

jar {
  manifest { 
    attributes "Main-Class": "$mainClassName"
  }  

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

古いgradleバージョンの場合、または依存関係に「コンパイル」修飾子をまだ使用している場合、これは機能するはずです:

// Include dependent libraries in archive.
mainClassName = "com.company.application.Main"

jar {
  manifest { 
    attributes "Main-Class": "$mainClassName"
  }  

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

mainClassNameBEFOREの前に現れる必要があることに注意してくださいjar {


4
ランタイムの依存関係もあるので、これをプロジェクトのconfiguration.runtime.collectに変更する必要がありました。
vextorspace 2016年

2
def mainClassNameコードを機能させるために追加する必要がありました...受け取っていましたルートプロジェクトの不明なプロパティ 'mainClassName'を設定できませんでした
hanskoff

1
ファイル名の衝突をどのように処理しますか?異なるJARの同じパスにあるファイルは上書きされます。
WST

3
残念ながら、これはもう機能しません。私はgradle 4.10と新しいimplementation構成を使用しますが、現在は非推奨ですcompile。上記のコードは、依存関係のない小さなjarファイルを作成します。変更すると(from { configurations.implementation.collect {...} })、構成の「実装」を直接解決できないというエラーが発生します
Bastian Voigt

1
@BastianVoigt configurations.compileClasspathはすべてのを修正しますimplementationが、api依存関係はafikのままにします。ソリューションの別の回答でここに見つかりましたruntimeClasspath。これにはapi依存関係も含まれます。
1

64

@felixからの返事は私をほとんどそこに連れて行ってくれました。私には2つの問題がありました。

  1. Gradle 1.5では、マニフェストタグがfatJarタスク内で認識されなかったため、Main-Class属性を直接設定できませんでした
  2. jarファイルに競合する外部META-INFファイルがありました。

次の設定はこれを解決します

jar {
  manifest {
    attributes(
      'Main-Class': 'my.project.main',
    )
  }
}

task fatJar(type: Jar) {
  manifest.from jar.manifest
  classifier = 'all'
  from {
    configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
  } {
    exclude "META-INF/*.SF"
    exclude "META-INF/*.DSA"
    exclude "META-INF/*.RSA"
  }
  with jar
}

これを標準のアセンブルまたはビルドタスクに追加するには、以下を追加します。

artifacts {
    archives fatJar
}

編集:@mjaggardのおかげで:のGradleの最近のバージョンでは、変更configurations.runtimeconfigurations.runtimeClasspath


3
これにより、依存関係のjarファイルの1つが署名されたときに発生した問題も修正されました。署名ファイルは私のjarのMETA-INFに入れられましたが、署名がコンテンツと一致しなくなりました。
Flavin

2
特別な感謝artifacts:まさに私が探していたもの。
AlexR 2017年

あなたが実行するとgradle fatJar、実行時の依存関係を、彼らはコピーすることはできませんので、コンパイルされていないようです。
mjaggard 2018年

64

あなたがしたい場合はjar、タスクが正常に動作しても、追加の持っているfatJarタスクを、以下を使用します。

task fatJar(type: Jar) {
    classifier = 'all'
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
    with jar
}

重要な部分はwith jarです。それがなければ、このプロジェクトのクラスは含まれません。


1
あなたはに署名したjarファイルを使用している場合にも、次の問題を参照してください含まれており、署名に問題に遭遇:stackoverflow.com/questions/999489/...
ピーターN.シュタインメッツ

6
これは動作しません。このソリューションでは、マニフェストファイルは空です。
Jonas、

4
私の2セント:名前を変更するよりも分類子を設定する方が良いです。baseName = project.name + '-all'の代わりにclassifier = 'all'を配置します。これにより、アーティファクト名をMaven / Nexusのポリシーに準拠した状態に保つことができます。
taciosd

1
追加group "build"して、このタスクはになりますbuild他のタスク、すなわちで(グループjarタスク。
MAGx2

1
with jarキーワードに関するドキュメントが見つかりません。具体的には何をしますか?
Philipp Hemmelmayr

9

これは私にとってはうまくいきます。

私のメインクラス:

package com.curso.online.gradle;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

public class Main {

    public static void main(String[] args) {
        Logger logger = Logger.getLogger(Main.class);
        logger.debug("Starting demo");

        String s = "Some Value";

        if (!StringUtils.isEmpty(s)) {
            System.out.println("Welcome ");
        }

        logger.debug("End of demo");
    }

}

そして、それは私のファイルbuild.gradleの内容です:

apply plugin: 'java'

apply plugin: 'eclipse'

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
    testCompile group: 'junit', name: 'junit', version: '4.+'
    compile  'org.apache.commons:commons-lang3:3.0'
    compile  'log4j:log4j:1.2.16'
}

task fatJar(type: Jar) {
    manifest {
        attributes 'Main-Class': 'com.curso.online.gradle.Main'
    }
    baseName = project.name + '-all'
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
    with jar
}

そして、私は自分のコンソールに次のように書きます:

java -jar ProyectoEclipseTest-all.jar

そして出力は素晴らしいです:

log4j:WARN No appenders could be found for logger (com.curso.online.gradle.Main)
.
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more in
fo.
Welcome

6

メインの実行可能クラスでファットJARを生成し、署名付きJARの問題を回避するには、gradle-one-jarプラグインをお勧めしますOne-JARプロジェクトを使用するシンプルなプラグイン。

使いやすい:

apply plugin: 'gradle-one-jar'

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.github.rholder:gradle-one-jar:1.0.4'
    }
}

task myjar(type: OneJar) {
    mainClass = 'com.benmccann.gradle.test.WebServer'
}

5

単純なソリューション

jar {
    manifest {
        attributes 'Main-Class': 'cova2.Main'
    } 
    doFirst {
        from { configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) } }
    }
}

5

私の依存関係が大きすぎて次のエラーが発生したことを除いて、@ benからの答えはほとんど私にとってうまくいきます

Execution failed for task ':jar'.
> archive contains more than 65535 entries.

  To build this archive, please enable the zip64 extension.

この問題を解決するには、次のコードを使用する必要があります

mainClassName = "com.company.application.Main"

jar {
  manifest { 
    attributes "Main-Class": "$mainClassName"
  }  
  zip64 = true
  from {
    configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
  }
}

1

プロジェクトから複数のjarを構築する必要がある人向け。

Gradleで関数を作成します。

void jarFactory(Jar jarTask, jarName, mainClass) {
    jarTask.doFirst {
        println 'Build jar ' + jarTask.name + + ' started'
    }

    jarTask.manifest {
        attributes(
                'Main-Class':  mainClass
        )
    }
    jarTask.classifier = 'all'
    jarTask.baseName = jarName
    jarTask.from {
        configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
    }
    {
        exclude "META-INF/*.SF"
        exclude "META-INF/*.DSA"
        exclude "META-INF/*.RSA"
    }
    jarTask.with jar 
    jarTask.doFirst {
        println 'Build jar ' + jarTask.name + ' ended'
    }
}

次に呼び出します:

task makeMyJar(type: Jar) {
    jarFactory(it, 'MyJar', 'org.company.MainClass')
}

Gradle 5で動作します。

jarはに配置され./build/libsます。


0

shadowJarプラグインでタスクを使用します. com.github.jengelman.gradle.plugins:shadow:5.2.0

実行./gradlew app::shadowJar 結果ファイルのみが使用されますMyProject/app/build/libs/shadow.jar

トップレベルbuild.gradleファイル:

 apply plugin: 'kotlin'

buildscript {
    ext.kotlin_version = '1.3.61'

    repositories {
        mavenLocal()
        mavenCentral()
        jcenter()
    }

    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath 'com.github.jengelman.gradle.plugins:shadow:5.2.0'
    }
}

アプリモジュールレベルのbuild.gradleファイル

apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'kotlin-kapt'
apply plugin: 'application'
apply plugin: 'com.github.johnrengelman.shadow'

sourceCompatibility = 1.8

kapt {
    generateStubs = true
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation "org.seleniumhq.selenium:selenium-java:4.0.0-alpha-4"
    shadow "org.seleniumhq.selenium:selenium-java:4.0.0-alpha-4"

    implementation project(":module_remote")
    shadow project(":module_remote")
}

jar {
    exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.MF'
    manifest {
        attributes(
                'Main-Class': 'com.github.kolyall.TheApplication',
                'Class-Path': configurations.compile.files.collect { "lib/$it.name" }.join(' ')
        )
    }
}

shadowJar {
    baseName = 'shadow'
    classifier = ''
    archiveVersion = ''
    mainClassName = 'com.github.kolyall.TheApplication'

    mergeServiceFiles()
}


0

Gradle 6.3、Javaライブラリ。「jarタスク」のコードは、「gradle build」タスクを実行するときに「build / libs / xyz.jar」に依存関係を追加します。

plugins {
    id 'java-library'
}

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

-1

アリに慣れている場合は、Gradleでも同じことを試すことができます。

task bundlemyjava{
    ant.jar(destfile: "build/cookmyjar.jar"){
        fileset(dir:"path to your source", includes:'**/*.class,*.class', excludes:'if any')
        } 
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.