如何使用GradleKotlin脚本创建一个胖JAR?

m1m5dgzv  于 2022-11-14  发布在  Kotlin
关注(0)|答案(4)|浏览(138)

正如标题所示,我想知道如何修改gradle.build.kts,以便有一个任务来创建一个唯一的jar,其中包含所有的依赖项(包括Kotlin库)。
我在Groovy中找到了以下示例:

  1. //create a single Jar with all dependencies
  2. task fatJar(type: Jar) {
  3. manifest {
  4. attributes 'Implementation-Title': 'Gradle Jar File Example',
  5. 'Implementation-Version': version,
  6. 'Main-Class': 'com.mkyong.DateUtils'
  7. }
  8. baseName = project.name + '-all'
  9. from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
  10. with jar
  11. }

但我不知道我怎么能写在Kotlin,除了:

  1. task("fatJar") {
  2. }
hpcdzsge

hpcdzsge1#

下面是一个不使用插件的版本,更像是Groovy版本。

  1. import org.gradle.jvm.tasks.Jar
  2. val fatJar = task("fatJar", type = Jar::class) {
  3. baseName = "${project.name}-fat"
  4. manifest {
  5. attributes["Implementation-Title"] = "Gradle Jar File Example"
  6. attributes["Implementation-Version"] = version
  7. attributes["Main-Class"] = "com.mkyong.DateUtils"
  8. }
  9. from(configurations.runtime.map({ if (it.isDirectory) it else zipTree(it) }))
  10. with(tasks["jar"] as CopySpec)
  11. }
  12. tasks {
  13. "build" {
  14. dependsOn(fatJar)
  15. }
  16. }

Also explained here
一些评论者指出,这在较新的Gradle版本中不再起作用。

  1. import org.gradle.jvm.tasks.Jar
  2. val fatJar = task("fatJar", type = Jar::class) {
  3. baseName = "${project.name}-fat"
  4. manifest {
  5. attributes["Implementation-Title"] = "Gradle Jar File Example"
  6. attributes["Implementation-Version"] = version
  7. attributes["Main-Class"] = "com.mkyong.DateUtils"
  8. }
  9. from(configurations.runtimeClasspath.get().map({ if (it.isDirectory) it else zipTree(it) }))
  10. with(tasks.jar.get() as CopySpec)
  11. }
  12. tasks {
  13. "build" {
  14. dependsOn(fatJar)
  15. }
  16. }

请注意configurations.runtimeClasspath.get()with(tasks.jar.get() as CopySpec)的差异。

展开查看全部
kmynzznz

kmynzznz2#

请注意,前3种方法修改Gradle现有的Jar任务。

方法1:将库文件放在结果JAR旁边

此方法不需要application或任何其他插件。

  1. tasks.jar {
  2. manifest.attributes["Main-Class"] = "com.example.MyMainClass"
  3. manifest.attributes["Class-Path"] = configurations
  4. .runtimeClasspath
  5. .get()
  6. .joinToString(separator = " ") { file ->
  7. "libs/${file.name}"
  8. }
  9. }

请注意,Java要求我们对Class-Path属性使用相对URL。因此,我们不能使用Gradle依赖项的绝对路径(这也容易被更改,并且在其他系统上不可用)。如果您想使用绝对路径,也许this workaround可以。
使用以下命令创建JAR:

  1. ./gradlew jar

默认情况下,生成的JAR将在 build/libs/ 目录中创建。
创建JAR后,将库JAR复制到放置结果JAR的 libs/ 子目录中。确保库JAR文件的文件名中不包含空格(它们的文件名应与上面任务中的${file.name}变量指定的文件名匹配)。

方法二:在结果JAR文件(fat或uber JAR)中嵌入库

此方法也不需要任何Gradle插件。

  1. tasks.jar {
  2. manifest.attributes["Main-Class"] = "com.example.MyMainClass"
  3. val dependencies = configurations
  4. .runtimeClasspath
  5. .get()
  6. .map(::zipTree) // OR .map { zipTree(it) }
  7. from(dependencies)
  8. duplicatesStrategy = DuplicatesStrategy.EXCLUDE
  9. }

创建JAR与前面的方法完全相同。

方法三:使用Shadow plugin(创建一个fat或uber JAR)

  1. plugins {
  2. id("com.github.johnrengelman.shadow") version "6.0.0"
  3. }
  4. // Shadow task depends on Jar task, so these configs are reflected for Shadow as well
  5. tasks.jar {
  6. manifest.attributes["Main-Class"] = "org.example.MainKt"
  7. }

使用以下命令创建JAR:

  1. ./gradlew shadowJar

有关配置插件的更多信息,请参见Shadow文档。

方法四:创建新任务(而不是修改Jar任务)

  1. tasks.create("MyFatJar", Jar::class) {
  2. group = "my tasks" // OR, for example, "build"
  3. description = "Creates a self-contained fat JAR of the application that can be run."
  4. manifest.attributes["Main-Class"] = "com.example.MyMainClass"
  5. duplicatesStrategy = DuplicatesStrategy.EXCLUDE
  6. val dependencies = configurations
  7. .runtimeClasspath
  8. .get()
  9. .map(::zipTree)
  10. from(dependencies)
  11. with(tasks.jar.get())
  12. }

运行创建的JAR

  1. java -jar my-artifact.jar

使用以下试剂检测上述溶液:

  • Java 17语言
  • Gradle 7.1(使用Kotlin1.4.31进行 .kts 构建脚本)

请参阅官方Gradle文档以了解如何创建超级(胖)JAR。
如需信息清单的详细信息,请参阅Oracle Java Documentation: Working with Manifest files
有关tasks.create()tasks.register()之间的差异,请参见this post
请注意,您的resource files will be included in the JAR file automatically(假设它们被放置在 /src/main/resources/ 目录或任何在构建文件中设置为资源根目录的自定义目录中)。要访问应用程序中的资源文件,请使用以下代码(注意名称开头的/):

  • Kotlin
  1. val vegetables = MyClass::class.java.getResource("/vegetables.txt").readText()
  2. // Alternative ways:
  3. // val vegetables = object{}.javaClass.getResource("/vegetables.txt").readText()
  4. // val vegetables = MyClass::class.java.getResourceAsStream("/vegetables.txt").reader().readText()
  5. // val vegetables = object{}.javaClass.getResourceAsStream("/vegetables.txt").reader().readText()
  • Java语言
  1. var stream = MyClass.class.getResource("/vegetables.txt").openStream();
  2. // OR var stream = MyClass.class.getResourceAsStream("/vegetables.txt");
  3. var reader = new BufferedReader(new InputStreamReader(stream));
  4. var vegetables = reader.lines().collect(Collectors.joining("\n"));
展开查看全部
vwkv1x7d

vwkv1x7d3#

以下是从Gradle 6.5.1,Kotlin/Kotlin-Multiplatform 1.3.72开始的实现方法,使用一个build.gradle.kts文件,而不使用额外的插件,这看起来确实是不必要的,而且在多平台环境下会出现问题;
注意:在现实中,很少有插件能很好地与多平台插件一起工作,这就是为什么我怀疑它的设计理念是如此冗长。它实际上是相当优雅的IMHO,但不够灵活或文档化,所以它需要大量的试验和错误来安装,即使没有额外的插件。
希望这对其他人有帮助。

  1. kotlin {
  2. jvm {
  3. compilations {
  4. val main = getByName("main")
  5. tasks {
  6. register<Jar>("fatJar") {
  7. group = "application"
  8. manifest {
  9. attributes["Implementation-Title"] = "Gradle Jar File Example"
  10. attributes["Implementation-Version"] = archiveVersion
  11. attributes["Main-Class"] = "[[mainClassPath]]"
  12. }
  13. archiveBaseName.set("${project.name}-fat")
  14. from(main.output.classesDirs, main.compileDependencyFiles)
  15. with(jar.get() as CopySpec)
  16. }
  17. }
  18. }
  19. }
  20. }
展开查看全部
hivapdat

hivapdat4#

您可以使用ShadowJar plugin构建一个fat jar:

  1. import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
  2. buildscript {
  3. repositories {
  4. mavenCentral()
  5. gradleScriptKotlin()
  6. }
  7. dependencies {
  8. classpath(kotlinModule("gradle-plugin"))
  9. classpath("com.github.jengelman.gradle.plugins:shadow:1.2.3")
  10. }
  11. }
  12. apply {
  13. plugin("kotlin")
  14. plugin("com.github.johnrengelman.shadow")
  15. }
  16. repositories {
  17. mavenCentral()
  18. }
  19. val shadowJar: ShadowJar by tasks
  20. shadowJar.apply {
  21. manifest.attributes.apply {
  22. put("Implementation-Title", "Gradle Jar File Example")
  23. put("Implementation-Version" version)
  24. put("Main-Class", "com.mkyong.DateUtils")
  25. }
  26. baseName = project.name + "-all"
  27. }

只需使用“shadowJar”运行任务。
注意:这假设您使用的是GSK 0.7.0(最新版本截至2017年2月13日)。

展开查看全部

相关问题