Maven Publish Plugin
The Maven Publish Plugin provides the ability to publish build artifacts to an Apache Maven repository. A module published to a Maven repository can be consumed by Maven, Gradle (see Declaring Dependencies) and other tools that understand the Maven repository format. You can learn about the fundamentals of publishing in Publishing Overview.
Usage
To use the Maven Publish Plugin, include the following in your build script:
plugins {
id 'maven-publish'
}
plugins {
`maven-publish`
}
The Maven Publish Plugin uses an extension on the project named publishing
of type PublishingExtension. This extension provides a container of named publications and a container of named repositories. The Maven Publish Plugin works with MavenPublication publications and MavenArtifactRepository repositories.
Tasks
generatePomFileForPubNamePublication
— GenerateMavenPom-
Creates a POM file for the publication named PubName, populating the known metadata such as project name, project version, and the dependencies. The default location for the POM file is build/publications/$pubName/pom-default.xml.
publishPubNamePublicationToRepoNameRepository
— PublishToMavenRepository-
Publishes the PubName publication to the repository named RepoName. If you have a repository definition without an explicit name, RepoName will be "Maven".
publishPubNamePublicationToMavenLocal
— PublishToMavenLocal-
Copies the PubName publication to the local Maven cache — typically $USER_HOME/.m2/repository — along with the publication’s POM file and other metadata.
publish
-
Depends on: All
publishPubNamePublicationToRepoNameRepository
tasksAn aggregate task that publishes all defined publications to all defined repositories. It does not include copying publications to the local Maven cache.
publishToMavenLocal
-
Depends on: All
publishPubNamePublicationToMavenLocal
tasksCopies all defined publications to the local Maven cache, including their metadata (POM files, etc.).
Publications
This plugin provides publications of type MavenPublication. To learn how to define and use publications, see the section on basic publishing.
There are four main things you can configure in a Maven publication:
-
A component — via MavenPublication.from(org.gradle.api.component.SoftwareComponent).
-
Custom artifacts — via the MavenPublication.artifact(java.lang.Object) method. See MavenArtifact for the available configuration options for custom Maven artifacts.
-
Standard metadata like
artifactId
,groupId
andversion
. -
Other contents of the POM file — via MavenPublication.pom(org.gradle.api.Action).
You can see all of these in action in the complete publishing example. The API documentation for MavenPublication
has additional code samples.
Identity values in the generated POM
The attributes of the generated POM file will contain identity values derived from the following project properties:
-
groupId
- Project.getGroup() -
artifactId
- Project.getName() -
version
- Project.getVersion()
Overriding the default identity values is easy: simply specify the groupId
, artifactId
or version
attributes when configuring the MavenPublication.
publishing {
publications {
maven(MavenPublication) {
groupId = 'org.gradle.sample'
artifactId = 'project1-sample'
version = '1.1'
from components.java
}
}
}
publishing {
publications {
create<MavenPublication>("maven") {
groupId = "org.gradle.sample"
artifactId = "project1-sample"
version = "1.1"
from(components["java"])
}
}
}
💡
|
Certain repositories will not be able to handle all supported characters. For example, the |
Maven restricts groupId
and artifactId
to a limited character set ([A-Za-z0-9_\\-.]+
) and Gradle enforces this restriction. For version
(as well as the artifact extension
and classifier
properties), Gradle will handle any valid Unicode character.
The only Unicode values that are explicitly prohibited are \
, /
and any ISO control character. Supplied values are validated early in publication.
Customizing the generated POM
The generated POM file can be customized before publishing. For example, when publishing a library to Maven Central you will need to set certain metadata. The Maven Publish Plugin provides a DSL for that purpose. Please see MavenPom in the DSL Reference for the complete documentation of available properties and methods. The following sample shows how to use the most common ones:
publishing {
publications {
mavenJava(MavenPublication) {
pom {
name = 'My Library'
description = 'A concise description of my library'
url = 'http://www.example.com/library'
licenses {
license {
name = 'The Apache License, Version 2.0'
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
developers {
developer {
id = 'johnd'
name = 'John Doe'
email = 'john.doe@example.com'
}
}
scm {
connection = 'scm:git:git://example.com/my-library.git'
developerConnection = 'scm:git:ssh://example.com/my-library.git'
url = 'http://example.com/my-library/'
}
}
}
}
}
publishing {
publications {
create<MavenPublication>("mavenJava") {
pom {
name.set("My Library")
description.set("A concise description of my library")
url.set("http://www.example.com/library")
licenses {
license {
name.set("The Apache License, Version 2.0")
url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
}
}
developers {
developer {
id.set("johnd")
name.set("John Doe")
email.set("john.doe@example.com")
}
}
scm {
connection.set("scm:git:git://example.com/my-library.git")
developerConnection.set("scm:git:ssh://example.com/my-library.git")
url.set("http://example.com/my-library/")
}
}
}
}
}
Repositories
This plugin provides repositories of type MavenArtifactRepository. To learn how to define and use repositories for publishing, see the section on basic publishing.
Here’s a simple example of defining a publishing repository:
publishing {
repositories {
maven {
// change to point to your repo, e.g. http://my.org/repo
url = "$buildDir/repo"
}
}
}
publishing {
repositories {
maven {
// change to point to your repo, e.g. http://my.org/repo
url = uri("$buildDir/repo")
}
}
}
The two main things you will want to configure are the repository’s:
-
URL (required)
-
Name (optional)
You can define multiple repositories as long as they have unique names within the build script. You may also declare one (and only one) repository without a name. That repository will take on an implicit name of "Maven".
You can also configure any authentication details that are required to connect to the repository. See MavenArtifactRepository for more details.
Snapshot and release repositories
It is a common practice to publish snapshots and releases to different Maven repositories. A simple way to accomplish this is to configure the repository URL based on the project version. The following sample uses one URL for versions that end with "SNAPSHOT" and a different URL for the rest:
publishing {
repositories {
maven {
def releasesRepoUrl = "$buildDir/repos/releases"
def snapshotsRepoUrl = "$buildDir/repos/snapshots"
url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
}
}
}
publishing {
repositories {
maven {
val releasesRepoUrl = "$buildDir/repos/releases"
val snapshotsRepoUrl = "$buildDir/repos/snapshots"
url = uri(if (version.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl)
}
}
}
Similarly, you can use a project or system property to decide which repository to publish to. The following example uses the release repository if the project property release
is set, such as when a user runs gradle -Prelease publish
:
publishing {
repositories {
maven {
def releasesRepoUrl = "$buildDir/repos/releases"
def snapshotsRepoUrl = "$buildDir/repos/snapshots"
url = project.hasProperty('release') ? releasesRepoUrl : snapshotsRepoUrl
}
}
}
publishing {
repositories {
maven {
val releasesRepoUrl = "$buildDir/repos/releases"
val snapshotsRepoUrl = "$buildDir/repos/snapshots"
url = uri(if (project.hasProperty("release")) releasesRepoUrl else snapshotsRepoUrl)
}
}
}
Publishing to Maven Local
For integration with a local Maven installation, it is sometimes useful to publish the module into the Maven local repository (typically at $USER_HOME/.m2/repository), along with its POM file and other metadata. In Maven parlance, this is referred to as 'installing' the module.
The Maven Publish Plugin makes this easy to do by automatically creating a PublishToMavenLocal task for each MavenPublication in the publishing.publications
container. The task name follows the pattern of publishPubNamePublicationToMavenLocal
. Each of these tasks is wired into the publishToMavenLocal
aggregate task. You do not need to have mavenLocal()
in your publishing.repositories
section.
Complete example
The following example demonstrates how to sign and publish a Java library including sources, Javadoc, and a customized POM:
plugins {
id 'java-library'
id 'maven-publish'
id 'signing'
}
group = 'com.example'
version = '1.0'
task sourcesJar(type: Jar) {
from sourceSets.main.allJava
classifier = 'sources'
}
task javadocJar(type: Jar) {
from javadoc
classifier = 'javadoc'
}
publishing {
publications {
mavenJava(MavenPublication) {
artifactId = 'my-library'
from components.java
artifact sourcesJar
artifact javadocJar
pom {
name = 'My Library'
description = 'A concise description of my library'
url = 'http://www.example.com/library'
licenses {
license {
name = 'The Apache License, Version 2.0'
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
developers {
developer {
id = 'johnd'
name = 'John Doe'
email = 'john.doe@example.com'
}
}
scm {
connection = 'scm:git:git://example.com/my-library.git'
developerConnection = 'scm:git:ssh://example.com/my-library.git'
url = 'http://example.com/my-library/'
}
}
}
}
repositories {
maven {
// change URLs to point to your repos, e.g. http://my.org/repo
def releasesRepoUrl = "$buildDir/repos/releases"
def snapshotsRepoUrl = "$buildDir/repos/snapshots"
url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
}
}
}
signing {
sign publishing.publications.mavenJava
}
javadoc {
if(JavaVersion.current().isJava9Compatible()) {
options.addBooleanOption('html5', true)
}
}
plugins {
`java-library`
`maven-publish`
signing
}
group = "com.example"
version = "1.0"
tasks.register<Jar>("sourcesJar") {
from(sourceSets.main.get().allJava)
classifier = "sources"
}
tasks.register<Jar>("javadocJar") {
from(tasks.javadoc)
classifier = "javadoc"
}
publishing {
publications {
create<MavenPublication>("mavenJava") {
artifactId = "my-library"
from(components["java"])
artifact(tasks["sourcesJar"])
artifact(tasks["javadocJar"])
pom {
name.set("My Library")
description.set("A concise description of my library")
url.set("http://www.example.com/library")
licenses {
license {
name.set("The Apache License, Version 2.0")
url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
}
}
developers {
developer {
id.set("johnd")
name.set("John Doe")
email.set("john.doe@example.com")
}
}
scm {
connection.set("scm:git:git://example.com/my-library.git")
developerConnection.set("scm:git:ssh://example.com/my-library.git")
url.set("http://example.com/my-library/")
}
}
}
}
repositories {
maven {
// change URLs to point to your repos, e.g. http://my.org/repo
val releasesRepoUrl = uri("$buildDir/repos/releases")
val snapshotsRepoUrl = uri("$buildDir/repos/snapshots")
url = if (version.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl
}
}
}
signing {
sign(publishing.publications["mavenJava"])
}
tasks.javadoc {
if (JavaVersion.current().isJava9Compatible) {
(options as StandardJavadocDocletOptions).addBooleanOption("html5", true)
}
}
The result is that the following artifacts will be published:
-
The POM:
my-library-1.0.pom
-
The primary JAR artifact for the Java component:
my-library-1.0.jar
-
The sources JAR artifact that has been explicitly configured:
my-library-1.0-sources.jar
-
The Javadoc JAR artifact that has been explicitly configured:
my-library-1.0-javadoc.jar
The Signing Plugin is used to generate a signature file for each artifact. In addition, checksum files will be generated for all artifacts and signature files.
Removal of deferred configuration behavior
Prior to Gradle 5.0, the publishing {}
block was (by default) implicitly treated as if all the logic inside it was executed after the project is evaluated.
This behavior caused quite a bit of confusion and was deprecated in Gradle 4.8, because it was the only block that behaved that way.
You may have some logic inside your publishing block or in a plugin that is depending on the deferred configuration behavior. For instance, the following logic assumes that the subprojects will be evaluated when the artifactId is set:
subprojects {
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
artifactId = jar.baseName
}
}
}
}
subprojects {
publishing {
publications {
create<MavenPublication>("mavenJava") {
from(components["java"])
artifactId = tasks.jar.get().baseName
}
}
}
}
This kind of logic must now be wrapped in an afterEvaluate {}
block.
subprojects {
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
afterEvaluate {
artifactId = jar.baseName
}
}
}
}
}
subprojects {
publishing {
publications {
create<MavenPublication>("mavenJava") {
from(components["java"])
afterEvaluate {
artifactId = tasks.jar.get().baseName
}
}
}
}
}