Configure Gradle to publish sources and javadoc - java

How do I configure Gradle to publish sources and javadoc jars to a repository?

Solution as of Gradle 6.0
Here’s the somewhat minimal configuration you can use if you’re on Gradle 6.0 or later; note the newly introduced withSourcesJar() and withJavadocJar() methods:
plugins {
id 'java'
id 'maven-publish'
}
group = 'com.example'
java {
withSourcesJar()
withJavadocJar()
}
publishing {
repositories {
maven {
url = 'file:///tmp/my-repo'
}
}
publications {
myJava(MavenPublication) {
from components.java
}
}
}
Of course, you can also use the ivy-publish plugin instead of maven-publish.
See also the Gradle docs:
on the two new methods
on the maven-publish plugin
on the ivy-publish plugin

Add the following code to the build script:
task packageJavadoc(type: Jar, dependsOn: 'javadoc') {
from javadoc.destinationDir
classifier = 'javadoc'
}
task packageSources(type: Jar, dependsOn: 'classes') {
from sourceSets.main.allSource
classifier = 'sources'
}
artifacts {
archives packageJavadoc
archives packageSources
}
Tested with Gradle 1.10

2017, Gradle 4.0 Edition:
apply plugin: 'maven'
apply plugin: 'maven-publish'
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
artifact sourceJar
artifact packageJavadoc
}
}
}
javadoc {
source = sourceSets.main.allJava
classpath = configurations.compileClasspath
options
{
setMemberLevel JavadocMemberLevel.PUBLIC
setAuthor true
links "https://docs.oracle.com/javase/8/docs/api/"
}
}
task sourceJar(type: Jar) {
classifier = 'sources'
from sourceSets.main.allJava
}
task packageJavadoc(type: Jar) {
from javadoc
classifier = 'javadoc'
}
Works with gradle publish and gradle publishToMavenLocal

Paolo Fulgoni's answer used to work for until I bumped up my Gradle version to 3.1. To get the packageJavadoc Task to work with Gradle 3.1 I found I had to make a slight tweak to it as follows:
task packageJavadoc(type: Jar) {
from javadoc
classifier = 'javadoc'
}

Related

What is the proper way to migrate this pom maven task to maven-publish?

I have this task in my build.gradle file that was using maven:
task pom {
doLast {
pom {
project {
groupId "${project.group}.${project.name}"
artifactId project.name
version project.version
}
}.writeTo ("$buildDir/libs/${project.name}.pom")
}
}
Now its my task to get this project ready for gradle 7, and part of that means upgrading maven to maven-publish. The above code snippit doesn't work with maven-publish, as pom() isn't a recognized method. What is the proper way to migrate this code over to maven-publish?
Try this, based on the Official Gradle Publishing Maven page:
publishing {
publications {
MavenCustom(MavenPublication) {
from components.java
groupId "${project.group}.${project.name}"
artifactId project.name
version project.version
}
}
}
model {
tasks.generatePomFileForMavenCustomPublication {
destination = file("$buildDir/libs/${project.name}.pom.xml")
}
}

sourcesJar task in gradle 5

I have inherited a codebase which I suspect was originally built with Gradle 4 (but I don't know for sure). I am using Gradle 5.5.1 and when I run gradle I get errors to do with publication to a Maven repo:
* What went wrong:
A problem occurred evaluating root project 'common'.
> Could not find method sourcesJar() for arguments [build_d1u03z05r8d12r3e8b5qq1fxm$_run_closure3$_closure13$_closure15$_closure16#190bc2b8] on object of type org.gradle.api.publish.maven.internal.publication.DefaultMavenPublication.
Add sourcesJar task to custom Gradle plugin looks like a similar problem but it is a different error and their solution doesn't work anyway.
The relevant parts of my build.gradle are:
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
artifact sourcesJar {
classifier "sources"
}
artifact testJar {
classifier "tests"
}
}
}
repositories {
maven {
url 'http://repo.url'
credentials {
username "$username"
password "$password"
}
}
}
}
task sourcesJar(type: Jar) {
from sourceSets.main.allSource
classifier = 'sources'
}
task testJar(type: Jar) {
from sourceSets.test.output
classifier = 'tests'
}
Okay I think I figured it out: https://docs.gradle.org/5.5.1/userguide/publishing_maven.html#publishing_maven:deferred_configuration says that a publishing block was executed after the rest of the project in Gradle 4, but not in Gradle 5.
So, changing
artifact sourcesJar {
classifier "sources"
}
artifact testJar {
classifier "tests"
}
to
afterEvaluate {
artifact sourcesJar {
classifier "sources"
}
artifact testJar {
classifier "tests"
}
}
got me a little further. With that change I then got this error:
* What went wrong:
A problem occurred configuring root project 'common'.
> Cannot create a Publication named 'sourcesJar' because this container does not support creating elements by name alone. Please specify which subtype of Publication to create. Known subtypes are: MavenPublication
https://discuss.gradle.org/t/cannot-create-a-publication-named-x/3726 and Gradle: Using 'maven-publish' plugin in custom standalone plugin seem to suggest that a prefix of project. should fix it.
So changing it to:
afterEvaluate {
artifact project.sourcesJar {
classifier "sources"
}
artifact project.testJar {
classifier "tests"
}
}
seems to work, though I'm a little iffy on the project. prefix.
In my case I had to add the following that Gradle was aware about the artifacts:
java {
withJavadocJar()
withSourcesJar()
}
Then I was able to use it this way:
publishing.publications {
mavenJava(MavenPublication) {
from components.java
}
}
Javadoc as well as Sources were published. There seems to be no need to add the afterEvaluate block.
In this block:
artifact sourcesJar {
classifier "sources"
}
artifact testJar {
classifier "tests"
}
remove the closures...just make it look like this:
artifact sourcesJar
artifact testJar

Why will the resources (e.g images) in the jar file be removed when publish android library as AAR to maven repository in Android Gradle Plugin 3.0.

Here is my case.
I have an android library project with some jar file dependencies in 'libs' folder. The jar files contain some images files in it. The image files are in the 'assets' folder in the jar.(e.g. foo.jar/assets/bar.png) When I publish the project to private maven repository (Sonatype Nexus) with the project being built to AAR artifact:
On Android Gradle Plugin 2.2.2, everything is ok.
But when I upgrade to Android Gradle Plugin 3.0.0, the images in the jar file is missing, and assets folder is completely removed. It seems like Gradle Plugin 3.0.0 would strip out resources in the jar file.
Here is my Gradle script.
apply plugin: 'maven'
apply plugin: 'signing'
uploadArchives {
repositories {
mavenDeployer {
configurePOM(project, pom)
repository(url: "http://private-ip") {
authentication(userName: 'abc', password: 'abc')
}
snapshotRepository(url: "http://private-ip") {
authentication(userName: 'abc', password: 'abc')
}
}
}
}
task androidJavadocs(type: Javadoc) {
failOnError false
source = android.sourceSets.main.java.srcDirs
options {
links "http://docs.oracle.com/javase/7/docs/api/"
linksOffline "http://d.android.com/reference", "${android.sdkDirectory}/docs/reference"
}
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
}
task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
classifier = 'javadoc'
from androidJavadocs.destinationDir
}
task androidSourcesJar(type: Jar) {
classifier = 'sources'
from android.sourceSets.main.java.srcDirs
}
artifacts {
archives androidSourcesJar
archives androidJavadocsJar
}
private configurePOM(Project p, def pom) {
pom.project {
groupId 'com.xxx.android'
artifactId p.name
version "1.0.0"
name 'com.xxx.android'
packaging 'aar'
description "Lib For Android"
url "http://private-ip"
inceptionYear "2016"
licenses {
license {
name "The Apache Software License, Version 2.0"
url "http://xxx"
distribution "repo"
comments "A business - friendly OSS license"
}
}
developers {
developer {
id "android_team"
name "android_team"
email "android_team#xxx.com"
url "http://xxx"
}
}
}
}
Any help will be appreciated.

How to compile project with Google Checkstyle rules with gradle?

I am trying to use Google checkstyle configuration (https://github.com/checkstyle/checkstyle/blob/master/src/main/resources/google_checks.xml) but I am constantly getting an error on gradle check:
Unable to create a Checker: cannot initialize module TreeWalker - Unable to instantiate EmptyCatchBlock
I used Gradle to build the project. Below is my gradle.build.
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'checkstyle'
sourceCompatibility = 1.8
version = '1.0'
checkstyle {
toolVersion = "6.3"
}
task "create-dirs" << {
sourceSets*.java.srcDirs*.each { it.mkdirs() }
sourceSets*.resources.srcDirs*.each { it.mkdirs() }
}
jar {
manifest {
attributes 'Implementation-Title': 'xyz',
'Implementation-Version': 0.01
}
}
repositories {
mavenCentral()
}
dependencies {
compile (
['org.apache.logging.log4j:log4j-api:2.2'],
['org.apache.logging.log4j:log4j-core:2.2']
)
testCompile(
['junit:junit:4.11'],
['org.mockito:mockito-core:1.+']
)
}
test {
systemProperties 'property': 'value'
}
uploadArchives {
repositories {
flatDir {
dirs 'repos'
}
}
}
Also, when I try to add XML config file to Checkstyle plugin in IDEA I get similar error but with a stack trace:
org.infernus.idea.checkstyle.exception.CheckStylePluginException: <html><b>The CheckStyle rules file could not be loaded.</b><br>cannot initialize module TreeWalker - Unable to instantiate EmptyCatchBlock</html>
at org.infernus.idea.checkstyle.checker.CheckerFactory.blacklistAndShowMessage(CheckerFactory.java:234)
at org.infernus.idea.checkstyle.checker.CheckerFactory.createChecker(CheckerFactory.java:188)
at org.infernus.idea.checkstyle.checker.CheckerFactory.getOrCreateCachedChecker(CheckerFactory.java:98)
at org.infernus.idea.checkstyle.checker.CheckerFactory.getChecker(CheckerFactory.java:73)
at org.infernus.idea.checkstyle.checker.CheckerFactory.getChecker(CheckerFactory.java:41)
I cannot figure out what am I doing wrong. Any help would be appreciated.
Gradle version: 2.2
You can add this configuration into your build.gradle file:
configurations {
checkstyleOverride
}
dependencies {
checkstyleOverride('com.puppycrawl.tools:checkstyle:6.11.2')
}
tasks.withType(Checkstyle) {
checkstyleClasspath = project.configurations.checkstyleOverride
}
Enjoy!
The problem lies in the fact that com.puppycrawl.tools.checkstyle.checks.blocks.EmptyCatchBlockCheck was indeed added to checkstyle but for version 6.4-SNAPSHOT. As it can be seen in checkstyle repository (pom.xml history) version 6.4-SNAPSHOT was introduced on the 02.02.2015 and EmptyCatchBlockCheck class was created on 18.02.2015.
Gradle still uses version 6.3 as in the following log extract:
:checkstyleMain
Download https://repo1.maven.org/maven2/com/puppycrawl/tools/checkstyle/6.3/checkstyle-6.3.pom
So there's simply no class You'd like to use.
According to the docs checkstyle classpath can be specified with checkstyleClasspath property - you can try to set it up manually.
I've also prepared a demo with 6.4-SNAPSHOT version, it can be found here. Checkstyle jar was built with mvn clean package with source taken from this repo.
Here is an approach that works with the (currently) latest versions of Gradle & Checkstyle (Gradle 6.1.1 & Checkstyle 8.29):
plugins {
id 'java'
id 'checkstyle'
}
configurations {
checkstyleConfig
}
dependencies {
checkstyleConfig("com.puppycrawl.tools:checkstyle:8.29") { transitive = false }
}
checkstyle {
toolVersion '8.29'
config = resources.text.fromArchiveEntry(configurations.checkstyleConfig, 'google_checks.xml')
}
Note that the Checkstyle dependency excludes transitive dependencies, otherwise the resources.text.fromArchiveEntry will fail since multiple JAR files will be present, and it will be unable to select a single one.

How to build sources JAR with Gradle?

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.
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
}
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.
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
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.
this should work
assemble.dependsOn 'propertyJar'
task propertyJar(type: Jar) {
archiveName = "myJarName.jar"
from('src/main/resources') {
include '**'
}}
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
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)
}
}
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)
// ...
}
}
}
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
}

Categories

Resources