// Copyright 2017 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

[[publishing_maven]]
== Maven Publishing (new)


[NOTE]
====
This chapter describes the new <<feature_lifecycle,incubating>> Maven publishing support provided by the “`maven-publish`” plugin. Eventually this new publishing support will replace publishing via the `Upload` task.

_Note:_ Signing the generated POM file generated by this plugin is currently not supported. Future versions of Gradle might add this functionality. Please use the <<maven_plugin,Maven plugin>> for the purpose of publishing your artifacts to Maven Central.

If you are looking for documentation on the original Maven publishing support using the `Upload` task please see <<artifact_management>>.
====

This chapter describes how to publish build artifacts to an http://maven.apache.org/[Apache Maven] Repository. A module published to a Maven repository can be consumed by Maven, Gradle (see <<dependency_management>>) and other tools that understand the Maven repository format.


[[sec:the_mavenpublish_plugin]]
=== The “`maven-publish`” Plugin

The ability to publish in the Maven format is provided by the “`maven-publish`” plugin.

The “`publishing`” plugin creates an extension on the project named “`publishing`” of type api:org.gradle.api.publish.PublishingExtension[]. This extension provides a container of named publications and a container of named repositories. The “`maven-publish`” plugin works with api:org.gradle.api.publish.maven.MavenPublication[] publications and api:org.gradle.api.artifacts.repositories.MavenArtifactRepository[] repositories.

++++
<sample id="publishing_maven:apply_plugin" dir="maven-publish/quickstart" title="Applying the 'maven-publish' plugin">
    <sourcefile file="build.gradle" snippet="use-plugin"/>
</sample>
++++

Applying the “`maven-publish`” plugin does the following:

* Applies the “`publishing`” plugin
* Establishes a rule to automatically create a api:org.gradle.api.publish.maven.tasks.GenerateMavenPom[] task for each api:org.gradle.api.publish.maven.MavenPublication[] added (see <<publishing_maven:publications>>).
* Establishes a rule to automatically create a api:org.gradle.api.publish.maven.tasks.PublishToMavenRepository[] task for the combination of each api:org.gradle.api.publish.maven.MavenPublication[] added (see <<publishing_maven:publications>>), with each api:org.gradle.api.artifacts.repositories.MavenArtifactRepository[] added (see <<publishing_maven:repositories>>).
* Establishes a rule to automatically create a api:org.gradle.api.publish.maven.tasks.PublishToMavenLocal[] task for each api:org.gradle.api.publish.maven.MavenPublication[] added (see<<publishing_maven:publications>>).


[[publishing_maven:publications]]
=== Publications


[NOTE]
====
If you are not familiar with project artifacts and configurations, you should read the <<artifact_management>> that introduces these concepts. This chapter also describes “publishing artifacts” using a different mechanism than what is described in this chapter. The publishing functionality described here will eventually supersede that functionality.
====

Publication objects describe the structure/configuration of a publication to be created. Publications are published to repositories via tasks, and the configuration of the publication object determines exactly what is published. All of the publications of a project are defined in the api:org.gradle.api.publish.PublishingExtension#getPublications()[] container. Each publication has a unique name within the project.

For the “`maven-publish`” plugin to have any effect, a api:org.gradle.api.publish.maven.MavenPublication[] must be added to the set of publications. This publication determines which artifacts are actually published as well as the details included in the associated POM file. A publication can be configured by adding components, customizing artifacts, and by modifying the generated POM file directly.


[[sec:publishing_component_to_maven]]
==== Publishing a Software Component

The simplest way to publish a Gradle project to a Maven repository is to specify a api:org.gradle.api.component.SoftwareComponent[] to publish. The components presently available for publication are:

.Software Components
[cols="a,a,a,a", options="header"]
|===
| Name
| Provided By
| Artifacts
| Dependencies

| `java`
| <<java_plugin>>
| Generated jar file
| Dependencies from 'runtime' configuration

| `web`
| <<war_plugin>>
| Generated war file
| No dependencies
|===

In the following example, artifacts and runtime dependencies are taken from the `java` component, which is added by the `Java Plugin`.

++++
<sample dir="maven-publish/quickstart" id="publishing_maven:publish-component" title="Adding a MavenPublication for a Java component">
    <sourcefile file="build.gradle" snippet="publish-component"/>
</sample>
++++


[[sec:publishing_custom_artifacts_to_maven]]
==== Publishing custom artifacts

It is also possible to explicitly configure artifacts to be included in the publication. Artifacts are commonly supplied as raw files, or as instances of api:org.gradle.api.tasks.bundling.AbstractArchiveTask[] (e.g. Jar, Zip).

For each custom artifact, it is possible to specify the `extension` and `classifier` values to use for publication. Note that only one of the published artifacts can have an empty classifier, and all other artifacts must have a unique classifier/extension combination.

Configure custom artifacts as follows:

++++
<sample dir="maven-publish/javaProject" id="publishing_maven:publish-custom-artifact" title="Adding additional artifact to a MavenPublication">
    <sourcefile file="build.gradle" snippet="publish-custom-artifact"/>
</sample>
++++

See the api:org.gradle.api.publish.maven.MavenPublication[] class in the API documentation for more information about how artifacts can be customized.

[[sec:identity_values_in_the_generated_pom]]
==== Identity values in the generated POM

The attributes of the generated `POM` file will contain identity values derived from the following project properties:

* `groupId` - api:org.gradle.api.Project#getGroup()[]
* `artifactId` - api:org.gradle.api.Project#getName()[]
* `version` - api:org.gradle.api.Project#getVersion()[]

Overriding the default identity values is easy: simply specify the `groupId`, `artifactId` or `version` attributes when configuring the `MavenPublication`.

++++
<sample dir="maven-publish/multiple-publications" id="publishing_maven:publish-customize-identity" title="customizing the publication identity">
    <sourcefile file="build.gradle" snippet="customize-identity"/>
</sample>
++++

[TIP]
====
Certain repositories will not be able to handle all supported characters. For example, the ':' character cannot be used as an identifier when publishing to a filesystem-backed repository on Windows.
====

Maven restricts 'groupId' and 'artifactId' to a limited character set (`[A-Za-z0-9_\\-.]+`) and Gradle enforces this restriction. For 'version' (as well as artifact 'extension' and 'classifier'), 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.

[[sec:modifying_the_generated_pom]]
==== Modifying the generated POM

The generated POM file may need to be tweaked before publishing. The “`maven-publish`” plugin provides a hook to allow such modification.

++++
<sample dir="maven-publish/pomCustomization" id="publishing_maven:pom_modification" title="Modifying the POM file">
    <sourcefile file="build.gradle" snippet="pom-modification"/>
</sample>
++++

In this example we are adding a 'description' element for the generated POM. With this hook, you can modify any aspect of the POM. For example, you could replace the version range for a dependency with the actual version used to produce the build.

See api:org.gradle.api.publish.maven.MavenPom#withXml(org.gradle.api.Action)[] in the API documentation for more information.

It is possible to modify virtually any aspect of the created POM. This means that it is also possible to modify the POM in such a way that it is no longer a valid Maven POM, so care must be taken when using this feature.

The identifier (groupId, artifactId, version) of the published module is an exception; these values cannot be modified in the POM using the `withXML` hook.

[[sec:publishing_multiple_modules_to_maven]]
==== Publishing multiple modules

Sometimes it's useful to publish multiple modules from your Gradle build, without creating a separate Gradle subproject. An example is publishing a separate API and implementation jar for your library. With Gradle this is simple:

++++
<sample dir="maven-publish/multiple-publications" id="publishing_maven:publish-multiple-publications" title="Publishing multiple modules from a single project">
     <sourcefile file="build.gradle" snippet="multiple-publications"/>
 </sample>
++++

If a project defines multiple publications then Gradle will publish each of these to the defined repositories. Each publication must be given a unique identity as described above.

[[publishing_maven:repositories]]
=== Repositories

Publications are published to repositories. The repositories to publish to are defined by the api:org.gradle.api.publish.PublishingExtension#getRepositories()[] container.

++++
<sample dir="maven-publish/quickstart" id="publishing_maven:repositories" title="Declaring repositories to publish to">
    <sourcefile file="build.gradle" snippet="repositories"/>
</sample>
++++

The DSL used to declare repositories for publication is the same DSL that is used to declare repositories to consume dependencies from, api:org.gradle.api.artifacts.dsl.RepositoryHandler[]. However, in the context of Maven publication only api:org.gradle.api.artifacts.repositories.MavenArtifactRepository[] repositories can be used for publication.

[[publishing_maven:publishing]]
=== Performing a publish

The “`maven-publish`” plugin automatically creates a api:org.gradle.api.publish.maven.tasks.PublishToMavenRepository[] task for each api:org.gradle.api.publish.maven.MavenPublication[] and api:org.gradle.api.artifacts.repositories.MavenArtifactRepository[] combination in the `publishing.publications` and `publishing.repositories` containers respectively.

The created task is named “`publish«_PUBNAME_»PublicationTo«_REPONAME_»Repository`”.

++++
<sample dir="maven-publish/quickstart" id="publishingMavenPublishMinimal" title="Publishing a project to a Maven repository">
    <sourcefile file="build.gradle"/>
    <output args="publish"/>
</sample>
++++

In this example, a task named “`publishMavenJavaPublicationToMavenRepository`” is created, which is of type api:org.gradle.api.publish.maven.tasks.PublishToMavenRepository[]. This task is wired into the `publish` lifecycle task. Executing “`gradle publish`” builds the POM file and all of the artifacts to be published, and transfers them to the repository.

[[publishing_maven:install]]
=== Publishing to Maven Local

For integration with a local Maven installation, it is sometimes useful to publish the module into the local .m2 repository. In Maven parlance, this is referred to as 'installing' the module. The “`maven-publish`” plugin makes this easy to do by automatically creating a api:org.gradle.api.publish.maven.tasks.PublishToMavenLocal[] task for each api:org.gradle.api.publish.maven.MavenPublication[] in the `publishing.publications` container. Each of these tasks is wired into the `publishToMavenLocal` lifecycle task. You do not need to have `mavenLocal` in your `publishing.repositories` section.

The created task is named “`publish«_PUBNAME_»PublicationToMavenLocal`”.

++++
<sample dir="maven-publish/quickstart" id="publishingMavenPublishLocal" title="Publish a project to the Maven local repository">
    <output args="publishToMavenLocal"/>
</sample>
++++

The resulting task in this example is named “`publishMavenJavaPublicationToMavenLocal`”. This task is wired into the `publishToMavenLocal` lifecycle task. Executing “`gradle publishToMavenLocal`” builds the POM file and all of the artifacts to be published, and “installs” them into the local Maven repository.

[[publishing_maven:generate-pom]]
=== Generating the POM file without publishing

At times it is useful to generate a Maven POM file for a module without actually publishing. Since POM generation is performed by a separate task, it is very easy to do so.

The task for generating the POM file is of type api:org.gradle.api.publish.maven.tasks.GenerateMavenPom[], and it is given a name based on the name of the publication: “`generatePomFileFor«_PUBNAME_»Publication`”. So in the example below, where the publication is named “`mavenCustom`”, the task will be named “`generatePomFileForMavenCustomPublication`”.

++++
<sample dir="maven-publish/pomCustomization" id="publishingMavenGeneratePom" title="Generate a POM file without publishing">
            <sourcefile file="build.gradle" snippet="generate"/>
            <output args="generatePomFileForMavenCustomPublication"/>
        </sample>
++++

All details of the publishing model are still considered in POM generation, including `components`, custom `artifacts`, and any modifications made via `pom.withXml`.

[NOTE]
====
The “`maven-publish`” plugin leverages some experimental support for late plugin configuration, and any `GenerateMavenPom` tasks will not be constructed until the publishing extension is configured. The simplest way to ensure that the publishing plugin is configured when you attempt to access the `GenerateMavenPom` task is to place the access inside a `model` block, as the example above demonstrates.

The same applies to any attempt to access publication-specific tasks like api:org.gradle.api.publish.maven.tasks.PublishToMavenRepository[]. These tasks should be referenced from within a `model` block.
====
