2014-02-12 134 views
81

到現在爲止,我通過Eclipse的「Export ...」功能創建了可運行的JAR文件,但現在我切換到了IntelliJ IDEA和Gradle以實現構建自動化。一些文章提出了「應用程序」插件,但這並不完全導致我期望的結果(只是一個JAR,沒有啓動腳本或類似的東西)。使用Gradle創建可運行的JAR

如何才能達到Eclipse使用「導出...」對話框所做的相同結果?

回答

89

可執行的JAR文件只是包含在其清單一個主級條目的jar文件。所以,你只需要以在其清單添加此項配置jar task

jar { 
    manifest { 
     attributes 'Main-Class': 'com.foo.bar.MainClass' 
    } 
} 

您可能還需要在清單中添加類路徑條目,但會做同樣的方式。

http://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.html

+3

這似乎是我正在尋找;但是:我已經在build.gradle中聲明瞭依賴關係,是否真的必須手動添加類路徑,還是可以重新使用我的依賴關係聲明? – Hannes

+0

您應該能夠遍歷'runtime'配置中的庫,並將它們連接起來以創建Class-Path屬性值。 –

+1

「inseid」運行時配置是什麼意思?對於愚蠢的問題抱歉,我對Gradle相當陌生... – Hannes

4

您是否嘗試過'installApp'任務?它不是用一組啓動腳本創建完整目錄嗎?

+0

據我瞭解,'installApp'不創建'META-INF/MANIFEST.MF'文件。難道我做錯了什麼? – advait

64

兩個JB Nizet和Jorge_B的答案是正確的。

以最簡單的形式,使用Gradle創建可執行JAR只是將適當的條目添加到manifest。然而,需要在類路徑中包含依賴關係更爲常見,這使得這種方法在實踐中變得棘手。

application plugin提供了一種替代方法;而不是創建一個可執行的JAR,它提供了:

  • 一個run任務,以便輕鬆地直接從構建
  • installDist任務產生包括內置JAR的目錄結構運行的應用程序,所有的JAR文件的這這取決於,而且拉它連成一個程序的啓動腳本,你可以運行創建一個包含一個完整的應用程序分發歸檔(啓動腳本和JAR)
  • distZipdistTar任務

第三種方法是創建一個所謂的「胖JAR」,它是一個可執行JAR,它不僅包含組件的代碼,還包含其所有依賴項。有幾種不同的插件使用這種方法。我已經包含了一些我知道的鏈接;我相信還有更多。

+0

只是試過陰影和一個罐子。我會堅持一個jar:它更簡單,更易於使用。涼!謝謝 – Jako

3

您可以定義模塊設置(或項目結構)的罐子神器。

  • 右鍵單擊具有依賴關係的模塊中的模塊>打開模塊設置>工件> +> JAR>。
  • 設置主類。

製作一個jar就像在Build菜單中點擊「Build artifact ...」一樣簡單。作爲獎勵,您可以將所有依賴關係打包到一個jar中。

經過IntelliJ IDEA 14 Ultimate測試。

24

正如其他人已經注意到的,爲了使jar文件可執行,必須在清單文件的Main-Class屬性中設置應用程序的入口點。如果依賴關係類文件不搭配,則需要在清單文件的Class-Path條目中設置它們。

我已經嘗試過各種插件組合,並且對於創建可執行jar以及某種方式的簡單任務來說,還包括依賴關係。所有插件似乎都缺乏這種或那種,但最終我得到了它,就像我想要的。沒有神祕的腳本,沒有百萬個不同的迷你文件污染了構建目錄,一個非常乾淨的構建腳本文件,最重要的是:沒有一百萬個外國第三方類文件合併到我的jar文件中。

下面是here爲了您的方便複製粘貼..

[操作指南]在子目錄/lib創建依賴罐子分佈zip文件,所有的依賴關係添加到清單Class-Path進入文件:

apply plugin: 'java' 
apply plugin: 'java-library-distribution' 

repositories { 
    mavenCentral() 
} 

dependencies { 
    compile 'org.apache.commons:commons-lang3:3.3.2' 
} 

// Task "distZip" added by plugin "java-library-distribution": 
distZip.shouldRunAfter(build) 

jar { 
    // Keep jar clean: 
    exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.MF' 

    manifest { 
     attributes 'Main-Class': 'com.somepackage.MainClass', 
        'Class-Path': configurations.runtime.files.collect { "lib/$it.name" }.join(' ') 
    } 
    // How-to add class path: 
    //  https://stackoverflow.com/questions/22659463/add-classpath-in-manifest-using-gradle 
    //  https://gist.github.com/simon04/6865179 
} 

作爲要點主辦here

結果可以在build/distributions發現並解壓縮後的內容是這樣的:

的lib /公地lang3-3.3.2.jar
myJarFile.jar中

內容的MyJarFile.jar#META-INF/MANIFEST.mf

Manifest-Version:1.0
主類:com.somepackage.MainClass
類路徑:LIB /公地lang3-3.3.2.jar

+0

當前的應用程序jar也將位於發行版的'lib'目錄中。您必須將其移動到頂部目錄或更改此行: 'Class-Path':configurations.runtime.files.collect {「lib/$ it.name」} .join('') } 對此: 'Class-Path':configurations.runtime.files.collect {「$ it.name」} .join('') } –

+1

@MarcNuri Are you sure?我嘗試在我的應用程序中使用這種方法,當前的應用程序jar在生成的zip/tar文件的'lib'目錄中是** not **,而是在'lib'的父目錄中,正如這個答案所暗示的。這個解決方案似乎對我來說非常合適。 – thejonwithnoh

+1

@thejonwithnoh對不起,你是對的。我沒有看到提出使用「java-library-distribution」插件的解決方案。就我而言,我只是簡單地使用「應用程序」插件來完成相同的工作,主要區別在於所有的jar文件(**包括應用程序jar)都位於「lib」目錄中。因此,將''lib/$ it.name'''改爲''$ it.name'''即可完成這項工作。 –

14

最省力的解決辦法是使用的gradle-shadow-plugin

除了應用插件,所有需要做的是:

  • 配置jar任務把主類成清單

    jar { manifest { attributes'Main-Class':'com.my.app。主 }}

  • 運行gradle這個任務./gradlew shadowJar

  • 採取應用程序版本,all.jar在編譯/庫/

最後通過執行它:

java -jar app-version-all.jar 
+1

這是[完整的'build.gradle'示例](https://gist.github.com/TurekBot/4a3cd406cb52dfd8bfb8022b982f0f6c)。 –

2

謝謝康斯坦丁,它的工作方式像一個幾乎沒有細微差別的魅力。出於某種原因,將main類指定爲jar清單的一部分並不完美,它需要改爲mainClassName屬性。下面是從的build.gradle片段,包括一切,使其工作:

plugins { 
    id 'java' 
    id 'com.github.johnrengelman.shadow' version '1.2.2' 
} 
... 
... 
apply plugin: 'application' 
apply plugin: 'com.github.johnrengelman.shadow' 
... 
... 
mainClassName = 'com.acme.myapp.MyClassMain' 
... 
... 
... 
shadowJar { 
    baseName = 'myapp' 
} 

運行gradle這個shadowJar後你會得到myapp- {}版本在-all.jar你的build文件夾可以作爲運行Java的罐子myapp- {}版本-all.jar。

2

我檢查了相當一些解決方案的鏈接,最後做了下面提到的步驟來讓它工作。我正在使用Gradle 2.9。

讓你構建了以下變化,gradle這個文件:

  1. 提到插件:

    apply plugin: 'eu.appsatori.fatjar' 
    
  2. 提供的Buildscript:

    buildscript { 
    repositories { 
        jcenter() 
    } 
    
    dependencies { 
        classpath "eu.appsatori:gradle-fatjar-plugin:0.3" 
    } 
    } 
    
  3. 提供主要類別:

    fatJar { 
        classifier 'fat' 
        manifest { 
        attributes 'Main-Class': 'my.project.core.MyMainClass' 
        } 
        exclude 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.SF' 
    } 
    
  4. 創建fatjar:

    ./gradlew clean fatjar 
    
  5. 運行從fatjar /建設/庫/:

    java -jar MyFatJar.jar 
    
相關問題