How to build sources JAR with Gradle?
Asked Answered
L

9

187

I am working with an open source project that is built with Gradle. I would like to generate a (project)-sources.jar file that I can load into my IDE (IntelliJ IDEA) and debug through the project. I know how to load the file if I can generate it.

I have looked through the available Gradle tasks for the project and there isn't one that generates a sources jar file.

What is the easiest way to generate a sources jar file for this project?

Adding the source into the jar file that contains the compiled class files would be fine as well.

Labrie answered 13/7, 2012 at 16:40 Comment(1)
Here is a similar post.Lambertson
O
264
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
}
Orvalorvan answered 13/7, 2012 at 17:5 Comment(11)
I'm accepting this answer based on the great specifics and my assumption it works on gradle projects that use the java plugin. Unfortunately, it doesn't work in my case as the project I'm using doesn't use the java plugin. The error I get is "Could not find property 'sourceSets' on task ':sourcesJar'."Labrie
In case it matters, the project referred to is hsqldb 2.2.8.Labrie
In my situation, the allSource property was not picking up the .java files, I had to change my sourcesJar task to use: from sourceSets.main.java, sourceSets.main.resourcesFibroin
If I'm not mistaken you also don't need the dependsOn specifications in the class. Gradle looks at the inputs for a task, determines where they came from, and automatically creates a dependency. e.g. javadocJar pulls files from javadoc, therefore Gradle will add the dependsOn javadoc automatically.Deerstalker
How can I reference the generated .jar files in Android Studio? Where do I have to put them?Osier
allSources is not available anymore.Dickman
allSource do exist?Aggress
Doug Ayers, I think you are right in theory, but without the dependsOn declaration, my Gradle (2.3) will build an empty jar.Aggress
Elaborated on the empty-jar issue here.Aggress
For me the dependsOn specification for the javadoc task is required (Gradle 2.3). Otherwise the created jar would be empty. The dependsOn specification for the classes task looks redundant. Why should one build the classes to create a source.jar? In the book Gradle In Action such a specification does not exist as well.Zymotic
Could not get unknown property 'classes' for project ':xxxx' of type org.gradle.api.Project.Neely
B
65

Solution as of Gradle 6.0

Assuming that you use the java/java-library plugin with Gradle 6.0 or later, you can get a sourcesJar task using the following configuration:

java {
    withSourcesJar()
    // and/or analogously use “withJavadocJar()” to get a “javadocJar” task
}

If you additionally use the maven-publish/ivy-publish plugin (recommended nowadays), then this will also publish a *-sources.jar artifact along with your main Java publication.

See also the Gradle docs.

Beginner answered 13/11, 2019 at 21:4 Comment(1)
This is the ideal solution for Gradle 6.0+ since this will also create the appropriate variants with the proper capabilities and attach them to the "java" component for publication. If you have additional components or variants then you can also call the internal helper function manually: JvmPluginsHelper.configureDocumentationVariantWithAritfact(mySourceSet.sourcesElementsConfigurationName, mySourceSet.name, DocsTypes.SOURCES, listOf(), mySourceSet.sourcesJarTaskName, mySourceSet.allSource, mySourceSetComponent, configurations, tasks, serviceOf().Phantasm
N
54

If you're using Android:

task sourcesJar(type: Jar) {
    from android.sourceSets.main.java.srcDirs
    classifier = 'sources'
}

task javadoc(type: Javadoc) {
    source = android.sourceSets.main.java.srcDirs
    classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
}

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

artifacts {
    archives javadocJar
    archives sourcesJar
}

from here

Nursemaid answered 10/3, 2015 at 16:45 Comment(0)
L
44

If you wish to add the sources to the compiled classes JAR file, which you also said would be acceptable, you can do that easily enough. Just add the following to your build file. You can see that, in theory, it is quite like the solution for putting sources into a separate JAR:

 jar {
     from sourceSets.main.allSource
 }

The difference is that you are adding it to the main JAR file by saying "jar" in lieu of sourcesJar.

Little answered 8/10, 2014 at 16:35 Comment(2)
In Android's gradle system, I'm getting this error: "Could not find method jar() for arguments on project of type org.gradle.api.Project"Featurelength
@Featurelength You should probably ask Giordano (author of the next answer) about that instead. I'm not an Android developer. https://mcmap.net/q/135183/-how-to-build-sources-jar-with-gradleLittle
J
12

this should work

assemble.dependsOn 'propertyJar'

task propertyJar(type: Jar) {
 archiveName = "myJarName.jar"
 from('src/main/resources') {
    include '**'
 }}
Julesjuley answered 9/7, 2015 at 11:21 Comment(1)
^ for this assemble.dependsOn part, which makes this task run automatically.Lilylilyan
D
9

When using:

  • Gradle: 5+
  • java and maven-publish plugins
task sourceJar(type: Jar) {
    from sourceSets.main.allJava
    archiveClassifier = "sources"
}

publishing {
    publications {
        maven(MavenPublication) {
            from components.java
            artifact sourceJar
        }
    }
}

https://docs.gradle.org/current/dsl/org.gradle.api.publish.maven.MavenPublication.html

Diandre answered 27/1, 2020 at 21:5 Comment(3)
Could not get unknown property 'main' for SourceSet container of type org.gradle.api.internal.tasks.DefaultSourceSetContainer any idea how to solve this?Neely
@RoshanaPitigala, what Gradle version are you using?Diandre
I had to use "from sourceSets.main.allSources" instead of .allJavaMusa
A
7

The Kotlin DSL equivalent would be:

tasks {

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

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

    artifacts {
        add("archives", sourcesJar)
        add("archives", javadocJar)
    }
}
Araucaria answered 3/1, 2018 at 3:12 Comment(4)
Not working for me under Gradle 5.0: Project."java" resolves to JavaPluginExtension which does not offer any sourceSets or docsDir properties.Cryo
Try using from(sourceSets["main"].allJava)Rhapsodic
changed from(javadoc) and from(sourceSets["main"].allSource)Kutzer
Also for kotlin DSL way please have a look on answer: https://mcmap.net/q/137195/-include-jar-file-with-java-sources-in-android-aarRufinaruford
L
2

This is how I included Dokka (view it online) and sources JARs for my Android Kotlin library using Kotlin DSL (build.gradle.kts):

plugins {
    // ...
    id("org.jetbrains.dokka") version "1.4.32"
    id("maven-publish")
}

lateinit var sourcesArtifact: PublishArtifact
lateinit var javadocArtifact: PublishArtifact

tasks {
    val sourcesJar by creating(Jar::class) {
        archiveClassifier.set("sources")
        from(android.sourceSets["main"].java.srcDirs)
    }
    val dokkaHtml by getting(org.jetbrains.dokka.gradle.DokkaTask::class)
    val javadocJar by creating(Jar::class) {
        dependsOn(dokkaHtml)
        archiveClassifier.set("javadoc")
        from(dokkaHtml.outputDirectory)
    }
    artifacts {
        sourcesArtifact = archives(sourcesJar)
        javadocArtifact = archives(javadocJar)
    }
}

publishing {
    // ...
    publications {
        create<MavenPublication>("MyPublication") {
            from(components["release"])
            artifact(sourcesArtifact)
            artifact(javadocArtifact)
            // ...
        }
    }
}
Lambertson answered 26/1, 2022 at 6:55 Comment(0)
T
0

Android:

  task androidSourcesJar(type: Jar) {
        getArchiveClassifier().set('sources')
        from android.sourceSets.main.java.srcDirs//full sources
  }

Java:

 task sourcesJar(type: Jar, dependsOn: classes) {
        getArchiveClassifier().set('sources')
        from sourceSets.main.allSource
    }
Tracy answered 9/2, 2022 at 10:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.