2014-02-12 189 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 
    
相关问题