Use of Gradle Kotlin DSL Jar.from()

≯℡__Kan透↙ 提交于 2020-06-29 04:00:10

问题


I'm trying to include a single source file for the Main-Class of a jar -- actually I have a toplevel directory of such files, demo/, but I don't want them all in a jar. I want separate jars, each using only one of these.

This seems like sort of an anti-pattern in gradle, as the fundamental mechanism infers or prefers that I should instead place each in a distinct sourceSet. Ugh.

A casual reading of the docs implies Jar.from() might be useful this way: "Specifies the source files or directories..."

As it turns out, "source" is perhaps a bit of a misnomer. Here's an example, a typical kotlin fat jar with the added from("demo/LockingBufferDemo.kt"):

val jar by tasks.getting(Jar::class) {
    manifest { attributes["Main-Class"] = "LockingBufferDemoKt" }
    from(sourceSets.main.get().output)
    from("demo/LockingBufferDemo.kt")
    dependsOn(configurations.runtimeClasspath)
    from({
        configurations.runtimeClasspath.get().filter {
            it.name.endsWith("jar") }.map { zipTree(it) }
    })
}         

Forgive my naivety: Guess what does not end up in the jar? LockingBufferDemo.class. Guess what does? LockingBufferDemo.kt. In other words, this is treated more like a resource, not a source, and what would have been the simplest answer is a dead end.

Another way to approach this would be add the demo directory as an independent sourceSet and then use from(sourceSets["demo"].get(), except I can't find a way to complete that; according to IntelliJ get() returns a rather opaque "Provider" which I can't find mentioned in the actual javadoc: 1, 2 and I really feel like I'm heading down the garden path at this point with the woods rapidly growing darker around me.

This should not be this complicated.

How can I add a single file (or class derived from such) into a jar in gradle without having to put it alone in a directory and create a sourceSet for every such directory?


回答1:


Regarding your explanations at the start of your post, you should consider creating multiple tasks of type Jar on your own, as every task of type Jar will only create a single JAR-file, and you "want separate jars". I do not think you should use different source sets, as all of the files are Java Kotlin source files in the end and are processed in the same way (compilation, tests, docs ...). Multiple source sets would complicate this common pipeline.

"Specifies the source files or directories..." As it turns out, "source" is perhaps a bit of a misnomer.

Well, the documentation does not stop there, but it says "for a copy and creates a child CopySpec". So it is not the source as in source code, but the source of a copy operation. In Gradle, tasks that create an archive (ZIP, JAR) share their API with tasks that copy files, as the creation of an archive can be seen as copying files from their source location to their target location (inside the archive).

So, the from method can be used to specify the files that are copied / archived. But it does not only take a sourcePath parameter, but also a closure or action for configuration. Using this second parameter, you can narrow your source files or directories down to the one file you need, for example using the method include:

val jar by tasks.getting(Jar::class) {
    manifest { attributes["Main-Class"] = "LockingBufferDemoKt" }
    from(sourceSets.main.get().output) {
        include("**/LockingBufferDemo.class")
    }
    dependsOn(configurations.runtimeClasspath)
    from({
        configurations.runtimeClasspath.get().filter {
            it.name.endsWith("jar") }.map { zipTree(it) }
    })
}


来源:https://stackoverflow.com/questions/62455921/use-of-gradle-kotlin-dsl-jar-from

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!