NOTE: You can open this sample inside an IDE using the https://www.jetbrains.com/help/idea/gradle.html#gradle_import_project_start[IntelliJ native importer] or https://projects.eclipse.org/projects/tools.buildship[Eclipse Buildship].

This sample shows how precompiled script plugins can be used to compose build logic using built-in Gradle plugins, external Gradle plugins and other utility classes.

== Use case

As an example, let's say an organization produces two types of Java software - services and libraries.
We want to apply a set of code quality checking rules to both types of projects and configure some aspects specific to each type.

This is achieved by layering three separate plugins:

* `com.example.java-convention` - configures conventions that are generic for any Java project in the organization.
* `com.example.library` - adds publishing configuration to publish to the organization's repository.
* `com.example.service` - adds integration tests and checks for mandatory content in a README.

We've put the plugins in the `plugins` directory in the sample. All plugins created in this sample contain functional tests that use link:{userManualPath}/test_kit.html[TestKit] to verify their behavior.

This root of this sample contains a consumer project that demonstrates how the plugins can be consumed using a link:{userManualPath}/composite_builds.html[composite build]:
====
include::sample[dir="groovy",files="settings.gradle[];build.gradle[]"]
include::sample[dir="kotlin",files="settings.gradle.kts[];build.gradle.kts[]"]
====

== Things to note

=== Applying an external plugin in precompiled script plugin

The `com.example.java-convention` plugin uses SpotBugs plugin to perform static code analysis.

SpotBugs is an external plugin - external plugins link:{userManualPath}/custom_plugins.html#applying_external_plugins_in_precompiled_script_plugins[need to be added as implementation dependencies] before they can be applied in a precompiled script plugin:
====
include::sample[dir="groovy",files="plugin/build.gradle[tags=repositories-and-dependencies]"]
include::sample[dir="kotlin",files="plugin/build.gradle.kts[tags=repositories-and-dependencies]"]
====

* The dependency artifact coordinates (GAV) for a plugin can be different from the plugin id.
* The Gradle Plugin Portal (`gradlePluginPortal()`) is added as a repository for plugin dependencies.
* The plugin version is determined from the dependency version.  Precompiled script plugins cannot supply a different version for now.

Once the dependency is added, the external plugin can be applied in precompiled script plugin by id:
====
include::sample[dir="groovy",files="plugin/src/main/groovy/com.example.java-convention.gradle[tags=apply-external-plugin]"]
include::sample[dir="kotlin",files="plugin/src/main/kotlin/com.example.java-convention.gradle.kts[tags=apply-external-plugin]"]
====

=== Applying other precompiled script plugins

Precompiled script plugins can apply other precompiled script plugins. 

The `com.example.library` and `com.example.service` plugins both apply the `com.example.java-convention` plugin:
====
include::sample[dir="groovy",files="plugin/src/main/groovy/com.example.library.gradle[tags=plugins];plugin/src/main/groovy/com.example.service.gradle[tags=plugins]"]
include::sample[dir="kotlin",files="plugin/src/main/kotlin/com.example.library.gradle.kts[tags=plugins];plugin/src/main/kotlin/com.example.service.gradle.kts[tags=plugins]"]
====

=== Using classes from the main source set

Precompiled script plugins can use classes defined in the main source set of the plugins project.

In this sample, `com.example.service` plugin uses a custom task class from `src/main/java` to configure service README checks:
====
include::sample[dir="groovy",files="plugin/src/main/groovy/com.example.service.gradle[tags=use-java-class]"]
include::sample[dir="kotlin",files="plugin/src/main/kotlin/com.example.service.gradle.kts[tags=use-java-class]"]
====

For more details on authoring custom Gradle plugins, consult the link:{userManualPath}/custom_plugins.html[user manual].
