186

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.

Mahozad
  • 18,032
  • 13
  • 118
  • 133
Paul D. Eden
  • 19,939
  • 18
  • 59
  • 63

9 Answers9

262
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
}
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • 4
    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'." – Paul D. Eden Jul 13 '12 at 17:32
  • In case it matters, the project referred to is hsqldb 2.2.8. – Paul D. Eden Jul 13 '12 at 17:57
  • 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.resources – Doug Ayers Oct 09 '13 at 18:06
  • 5
    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. – Mikezx6r Oct 25 '13 at 12:06
  • How can I reference the generated .jar files in Android Studio? Where do I have to put them? – JJD Nov 22 '13 at 19:55
  • allSources is not available anymore. – Daniele Segato Aug 19 '14 at 07:52
  • [allSource](https://gradle.org/docs/current/javadoc/org/gradle/api/tasks/SourceSet.html#getAllSource()) do exist? – Martin Andersson Mar 07 '15 at 20:33
  • Doug Ayers, I think you are right in theory, but without the `dependsOn` declaration, my Gradle (2.3) will build an empty jar. – Martin Andersson Mar 07 '15 at 20:34
  • Elaborated on the empty-jar issue [here](http://forums.gradle.org/gradle/topics/javadoc_and_jar_fails). – Martin Andersson Mar 07 '15 at 20:57
  • 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. – rwitzel Mar 29 '15 at 09:57
  • `Could not get unknown property 'classes' for project ':xxxx' of type org.gradle.api.Project.` – Roshana Pitigala Jun 02 '21 at 21:21
63

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.

Chriki
  • 15,638
  • 3
  • 51
  • 66
  • 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()`. – Mike Hill Aug 30 '21 at 16:04
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

Giordano
  • 1,401
  • 15
  • 26
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.

Michael Oryl
  • 20,856
  • 14
  • 77
  • 117
  • 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" – iamreptar Sep 21 '16 at 00:54
  • @iamreptar You should probably ask Giordano (author of the next answer) about that instead. I'm not an Android developer. http://stackoverflow.com/a/28969412/1480995 – Michael Oryl Sep 21 '16 at 11:25
12

this should work

assemble.dependsOn 'propertyJar'

task propertyJar(type: Jar) {
 archiveName = "myJarName.jar"
 from('src/main/resources') {
    include '**'
 }}
Ali
  • 1,480
  • 2
  • 20
  • 30
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

Artem Areshko
  • 159
  • 2
  • 6
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)
    }
}
wheleph
  • 7,974
  • 7
  • 40
  • 57
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)
            // ...
        }
    }
}
Mahozad
  • 18,032
  • 13
  • 118
  • 133
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
    }
NickUnuchek
  • 11,794
  • 12
  • 98
  • 138