19

This question asks how to build a SourceJar with Gradle. How can I do the same with the Gradle Kotlin DSL?

The gradle code would be:

task sourcesJar(type: Jar, dependsOn: classes) {
    classifier = 'sources'
    from sourceSets.main.allSource
}

task javadocJar(type: Jar, dependsOn: javadoc) {
    classifier = 'javadoc'
    from javadoc.destinationDir
}

artifacts {
    archives sourcesJar
    archives javadocJar
}
Morgoth
  • 4,935
  • 8
  • 40
  • 66

5 Answers5

26

With Gradle 5.3.1, this is a little nicer and avoids deprecated API:

tasks {    
    val sourcesJar by creating(Jar::class) {
        archiveClassifier.set("sources")
        from(sourceSets.main.get().allSource)
    }

    val javadocJar by creating(Jar::class) {
        dependsOn.add(javadoc)
        archiveClassifier.set("javadoc")
        from(javadoc)
    }

    artifacts {
        archives(sourcesJar)
        archives(javadocJar)
        archives(jar)
    }
}

Task assemble will create all the artifacts.

Raphael
  • 9,779
  • 5
  • 63
  • 94
17

The following will work:

val sourcesJar by creating(Jar::class) {
    dependsOn(JavaPlugin.CLASSES_TASK_NAME)
    classifier = "sources"
    from(sourceSets["main"].allSource)
}

val javadocJar by creating(Jar::class) {
    dependsOn(JavaPlugin.JAVADOC_TASK_NAME)
    classifier = "javadoc"
    from(tasks["javadoc"])
}

artifacts {
    add("archives", sourcesJar)
    add("archives", javadocJar)
}

A complete build.gradle.kts would look like this:

plugins {
    kotlin("jvm") version "1.2.71"
}

repositories {
    mavenCentral()
}

dependencies {
}

tasks {
    val sourcesJar by creating(Jar::class) {
        dependsOn(JavaPlugin.CLASSES_TASK_NAME)
        classifier = "sources"
        from(sourceSets["main"].allSource)
    }

    val javadocJar by creating(Jar::class) {
        dependsOn(JavaPlugin.JAVADOC_TASK_NAME)
        classifier = "javadoc"
        from(tasks["javadoc"])
    }

    artifacts {
        add("archives", sourcesJar)
        add("archives", javadocJar)
    }
}
Morgoth
  • 4,935
  • 8
  • 40
  • 66
  • With Gradle 5.0 the line `from(tasks["javadoc"])` no longer works as it resolves to a `TaskProvider` without any `get(int)` operation – bentolor Dec 03 '18 at 15:45
  • 1
    @BenjaminSchmid, try using `val javadocJar by creating(Jar::class) { val javadoc by tasks; from(javadoc); classifier = "javadoc"; }` – madhead Dec 04 '18 at 14:39
  • 1
    Thanks @madhead : Any idea how to delegate the accompaning `sourceSets["main"]`-call? – bentolor Dec 05 '18 at 12:31
  • `val main by sourcesets` :) – madhead Dec 05 '18 at 14:25
  • 2
    @BenjaminSchmid. Ok, it seems to be a problem particularly with multi-module projects. In single-module projects there is an extension in Kotlin DSL — `sourceSets`. But that accessor seems to be not generating in multi-module projects, probably due to a bug. But you can use delegates to get any property (it's like `methodMissing` in Groovy, actually). So here is a trick: `val sourcesJar by tasks.creating(Jar::class) { val sourceSets: SourceSetContainer by project; from(sourceSets["main"].allJava); classifier = "sources"; }`. Though, I don't like it it seems to be working. – madhead Dec 06 '18 at 15:21
15

As of Gradle 6.0 this is a much easier and cleaner. All you need to do is:

java {
    withSourcesJar()
    withJavadocJar()
}

Check out the documentation on the java extension, and its functions, withSourcesJar() and withJavadocJar()

Tom Hanley
  • 1,252
  • 11
  • 21
  • Expression 'java' cannot be invoked as a function. The function 'invoke()' is not found - if you try to use that in a subprojects block to make it work for subprojects as well. – Hakanai Jan 10 '21 at 22:16
  • 1
    Apparently the fix for that is to change it to `configure { ... }` – Hakanai Jan 11 '21 at 01:42
  • 2
    The Java plugin is not available for android libraries (not compatible last I checked) – Alix May 12 '21 at 11:25
3

All described methods fail with error on Gradle 6.6:
SourceSet with name 'main' not found

I've found a solution that works:

tasks {
    val sourcesJar by creating(Jar::class) {
        archiveClassifier.set("sources")
        from(android.sourceSets.getByName("main").java.srcDirs)
    }

    artifacts {
        archives(sourcesJar)
    }
}
Oleksandr Albul
  • 1,611
  • 1
  • 23
  • 31
-1

With Gradle 5.1 you can do something like this

tasks {
    val sourcesJar by registering(Jar::class) {
        classifier = "sources"
        from(sourceSets.main.get().allSource)
        dependsOn(classes)
    }
    val javadocJar by registering(Jar::class) {
        classifier = "javadoc"
        from(javadoc.get().destinationDir)
        dependsOn(javadoc)
    }
}
orjan
  • 1,482
  • 1
  • 19
  • 35