【问题标题】:How to create a fat JAR with Gradle Kotlin script?如何使用 gradle kotlin 脚本创建 fat jar
【发布时间】:2017-06-07 06:54:29
【问题描述】:

如标题所示,我想知道如何修改gradle.build.kts,以便创建一个独特的jar,其中包含所有依赖项(包括kotlin lib)。

我在 Groovy 中找到了这个示例:

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

但我不知道如何在 kotlin 中编写它,除了:

task("fatJar") {

}

【问题讨论】:

    标签: kotlin build.gradle gradle-kotlin-dsl build.gradle.kts


    【解决方案1】:

    这是从 Gradle 6.5.1、Kotlin/Kotlin-Multiplatform 1.3.72 开始的方法,使用 build.gradle.kts 文件而不使用额外的插件,这对于多平台来说似乎是不必要且有问题的;

    注意:据我所知,实际上很少有插件能很好地与多平台插件配合使用,这就是我怀疑它的设计理念本身如此冗长的原因。恕我直言,它实际上相当优雅,但不够灵活或没有足够的文档记录,因此即使没有额外的插件,也需要大量的试验和错误来设置。

    希望这对其他人有所帮助。

    kotlin {
        jvm {
            compilations {
                val main = getByName("main")
                tasks {
                    register<Jar>("fatJar") {
                        group = "application"
                        manifest {
                            attributes["Implementation-Title"] = "Gradle Jar File Example"
                            attributes["Implementation-Version"] = archiveVersion
                            attributes["Main-Class"] = "[[mainClassPath]]"
                        }
                        archiveBaseName.set("${project.name}-fat")
                        from(main.output.classesDirs, main.compileDependencyFiles)
                        with(jar.get() as CopySpec)
                    }
                }
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

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

      import org.gradle.jvm.tasks.Jar
      
      val fatJar = task("fatJar", type = Jar::class) {
          baseName = "${project.name}-fat"
          manifest {
              attributes["Implementation-Title"] = "Gradle Jar File Example"
              attributes["Implementation-Version"] = version
              attributes["Main-Class"] = "com.mkyong.DateUtils"
          }
          from(configurations.runtime.map({ if (it.isDirectory) it else zipTree(it) }))
          with(tasks["jar"] as CopySpec)
      }
      
      tasks {
          "build" {
              dependsOn(fatJar)
          }
      }
      

      Also explained here


      一些评论者指出,这不再适用于较新的 Gradle 版本。 使用 Gradle 5.4.1 测试的更新:

      import org.gradle.jvm.tasks.Jar
      
      val fatJar = task("fatJar", type = Jar::class) {
          baseName = "${project.name}-fat"
          manifest {
              attributes["Implementation-Title"] = "Gradle Jar File Example"
              attributes["Implementation-Version"] = version
              attributes["Main-Class"] = "com.mkyong.DateUtils"
          }
          from(configurations.runtimeClasspath.get().map({ if (it.isDirectory) it else zipTree(it) }))
          with(tasks.jar.get() as CopySpec)
      }
      
      tasks {
          "build" {
              dependsOn(fatJar)
          }
      }
      

      注意configurations.runtimeClasspath.get()with(tasks.jar.get() as CopySpec) 的区别。

      【讨论】:

      • 他不是在开玩笑。这应该添加到github.com/gradle/kotlin-dsl/tree/master/samples
      • 请注意,在 Gradle 5 中,您必须将 configurations.runtime.map 替换为 configurations.runtime.get().map 以避免 unresolved reference: isDirectory。见讨论here
      • 我还必须 exclude("META-INF/*.RSA", "META-INF/*.SF", "META-INF/*.DSA", "META-INF/INDEX.LIST") 才能在 jar 中找到主类
      • 必须在 fatJar 任务中使用 duplicatesStrategy = DuplicatesStrategy.EXCLUDE 或排除一些文件以避免失败 - 每个 jar 依赖项中的 LICENSE.txt 被包含在内,这导致了一些错误。
      • 这不再适用于 gradle 6.8
      【解决方案3】:

      您可以使用ShadowJar plugin 构建一个胖罐子:

      import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
      
      buildscript {
          repositories {
              mavenCentral()
              gradleScriptKotlin()
          }
          dependencies {
              classpath(kotlinModule("gradle-plugin"))
              classpath("com.github.jengelman.gradle.plugins:shadow:1.2.3")
          }
      }
      
      apply {
          plugin("kotlin")
          plugin("com.github.johnrengelman.shadow")
      }
      
      repositories {
          mavenCentral()
      }
      
      val shadowJar: ShadowJar by tasks
      shadowJar.apply {
          manifest.attributes.apply {
              put("Implementation-Title", "Gradle Jar File Example")
              put("Implementation-Version" version)
              put("Main-Class", "com.mkyong.DateUtils")
          }
      
          baseName = project.name + "-all"
      }
      

      只需使用“shadowJar”运行任务。

      注意:这假设您使用的是 GSK 0.7.0(最新的截至 2017 年 2 月 13 日)。

      【讨论】:

      • 不工作,在第一行import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJarShadowJar 未解决..
      • 从那以后你试过我的答案了吗?我已经对其进行了测试并且可以正常工作。我认为最初的问题是 the() 需要一个扩展类。
      • 我又试了一次right now,在tasks 上面写着[DELEGATE_SPECIAL_FUNCTION_MISSING] Missing 'getValue(Build_gradle, KProperty&lt;*&gt;)' method on delegate of type 'TaskContainer!'
      • 嗯,您确定使用最新的 GSK 吗?编译器和插件呢?
      • 我在最后一个here。如何检查编译器和插件?你能自己试一试here吗?我不知道,也许我在某处遗漏了一些基本步骤..
      猜你喜欢
      • 2019-08-29
      • 1970-01-01
      • 2020-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-27
      • 2019-12-01
      • 1970-01-01
      相关资源
      最近更新 更多