// Copyright (C) 2024 Gradle, Inc.
//
// Licensed under the Creative Commons Attribution-Noncommercial-ShareAlike 4.0 International License.;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://creativecommons.org/licenses/by-nc-sa/4.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.

[[java_gradle_plugin]]
= Gradle Plugin Development Plugin

The Java Gradle Plugin development plugin can be used to assist in the development of Gradle plugins.
It automatically applies the <<java_library_plugin.adoc#java_library_plugin,Java Library (`java-library`)>> plugin, adds the `gradleApi()` dependency to the `compileOnlyApi` configuration and performs validation of plugin metadata during `jar` task execution.

The plugin also integrates with <<test_kit.adoc#test_kit,TestKit>>, a library that aids in writing and executing functional tests for plugin code.
It automatically adds the `gradleTestKit()` dependency to the `testImplementation` configuration and generates a plugin classpath manifest file consumed by a `GradleRunner` instance if found.
Please refer to <<test_kit.adoc#sub:test-kit-automatic-classpath-injection,Automatic classpath injection with the Plugin Development Plugin>> for more on its usage, configuration options and samples.

[[sec:gradle_plugin_dev_usage]]
== Usage

To use the Java Gradle Plugin Development plugin, include the following in your build script:

====
include::sample[dir="snippets/java/javaGradlePlugin/kotlin",files="build.gradle.kts[tags=use-java-gradle-plugin-plugin]"]
include::sample[dir="snippets/java/javaGradlePlugin/groovy",files="build.gradle[tags=use-java-gradle-plugin-plugin]"]
====

Applying the plugin automatically applies the <<java_library_plugin.adoc#java_library_plugin,Java Library(`java-library`)>> plugin and adds the `gradleApi()` dependency to the `api` configuration.
It also adds some validations to the build.

The following validations are performed:

* There is a plugin descriptor defined for the plugin.
* The plugin descriptor contains an `implementation-class` property.
* The `implementation-class` property references a valid class file in the jar.
* Each property getter or the corresponding field must be annotated with a property annotation like `@InputFile` and `@OutputDirectory`.
Properties that don't participate in up-to-date checks should be annotated with `@Internal`.

Any failed validations will result in a warning message.

For each plugin you are developing, register it into the `gradlePlugin {}` script block:

====
include::sample[dir="snippets/java/javaGradlePlugin/kotlin",files="build.gradle.kts[tags=gradle-plugin-block]"]
include::sample[dir="snippets/java/javaGradlePlugin/groovy",files="build.gradle[tags=gradle-plugin-block]"]
====

The `gradlePlugin {}` block defines the plugins being built by the project.
The plugin `id` is set from the registration name, here `org.gradle.sample.simple-plugin`.
Then, you define the `implementationClass` of the plugin, here `org.gradle.sample.SimplePlugin`.

You can override the plugin `id` by explicitly setting the `id` property such as `id = "convention-plugin"`.

From this data about the plugins being developed, Gradle can automatically:

* Generate the plugin descriptor in the `jar` file's `META-INF` directory.
* Configure the <<plugins_intermediate.adoc#sec:plugin_markers,Plugin Marker Artifact>> publications (Maven or Ivy) for each plugin.
* Publish each plugin to the Gradle Plugin Portal (see <<publishing_gradle_plugins.adoc#publishing_portal,Publishing Plugins to Gradle Plugin Portal>> for details), but only if the link:https://plugins.gradle.org/docs/publish-plugin[Plugin Publishing Plugin] has also been applied.

[[sec:gradle_plugin_dev_interactions]]
== Interactions

Some of the plugin's behaviour depends on other, related plugins also being applied in your build, namely the <<publishing_maven.adoc#publishing_maven,Maven Publish (`maven-publish`)>> and <<publishing_ivy.adoc#publishing_ivy,Ivy Publish (`ivy-publish`)>> plugins.

Other plugins auto apply the Java Gradle Plugin, like the link:https://plugins.gradle.org/plugin/com.gradle.plugin-publish[Plugin Publishing Plugin].

=== Maven Publish Plugin

When the Java Gradle Plugin (`java-gradle-plugin`) detects that the Maven Publish Plugin (`maven-publish`) is also applied by the build, it will automatically configure the following link:{groovyDslPath}/org.gradle.api.publish.maven.MavenPublication.html[MavenPublications]:

* a single "main" publication, named `pluginMaven`, based on the <<java_plugin.adoc#sec:java_plugin_publishing,main Java component>>
* multiple <<plugins_intermediate.adoc#sec:plugin_markers,"marker" publications>> (one for each plugin defined in the `gradlePlugin {}` block), named `<pluginName>PluginMarkerMaven` (for example in the above example it would be `simplePluginPluginMarkerMaven`)

This automatic configuration happens in a link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:afterEvaluate(org.gradle.api.Action)[Project.afterEvaluate()] block (so at the end of the <<build_lifecycle.adoc#build_phases,build configuration phase>>), and only if these publications haven't already been defined, so it's possible to create and customise them during the earlier stages of build configuration.

=== Ivy Publish Plugin

When the Java Gradle Plugin(`java-gradle-plugin`) detects that the Ivy Publish Plugin (`ivy-publish`) is also applied by the build, it will automatically configure the following link:{groovyDslPath}/org.gradle.api.publish.ivy.IvyPublication.html[IvyPublications]:

* a single "main" publication, named `pluginIvy`, based on the <<java_plugin.adoc#sec:java_plugin_publishing,main Java component>>
* multiple <<plugins_intermediate.adoc#sec:plugin_markers,"marker" publications>> (one for each plugin defined in the `gradlePlugin {}` block), named `<pluginName>PluginMarkerIvy` (for example in the above example it would be `simplePluginPluginMarkerIvy`)

This automatic configuration happens in a link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:afterEvaluate(org.gradle.api.Action)[Project.afterEvaluate()] block (so at the end of the <<build_lifecycle.adoc#build_phases,build configuration phase>>), and only if these publications haven't already been defined, so it's possible to create and customise them during the earlier stages of build configuration.

=== Plugin Publish Plugin

Starting from link:https://plugins.gradle.org/plugin/com.gradle.plugin-publish/1.0.0[version 1.0.0, the Plugin Publish Plugin] always auto-applies the Java Gradle Plugin (`java-gradle-plugin`) and the Maven Publish Plugin (`maven-publish`).
