// Copyright (C) 2025 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.

[[pre_compiled_script_plugins_advanced]]
= Pre-compiled Script Plugins

The simplest plugin you can develop is called a *precompiled script plugins*.

These are Kotlin (`.kts`) or Groovy (`.gradle`) scripts.
They behave like normal Gradle plugins, but you write them using the same syntax as regular build scripts.

Some benefits of *precompiled script plugins*:

* **Encapsulation**: Keep your `build.gradle(.kts)` files clean by moving reusable logic into named plugins.
* **Tooling support**: Full IDE support, like autocomplete and navigation.
* **Avoid boilerplate**: No need to write full plugin classes or register plugins manually.
* **Faster adoption**: Use familiar script syntax while reaping the benefits of structured plugin development.

[[sec:convention_plugins_precompiled]]
== Convention Plugins

Most *precompiled script plugins* are used as *convention plugins*.
A Gradle term for reusable build logic that applies standard plugin configurations, defaults, and behaviors across many projects.

*Convention plugins* are especially useful in large or multi-project builds where consistency is important.

They typically look like this:

====
include::sample[dir="snippets/fundamentals/developing-plugins/precompiledScriptPlugins-inBuildSrc/kotlin", files="buildSrc/src/main/kotlin/java-library-convention.gradle.kts[]"]
include::sample[dir="snippets/fundamentals/developing-plugins/precompiledScriptPlugins-inBuildSrc/groovy", files="buildSrc/src/main/groovy/java-library-convention.gradle[]"]
====

And are applied in other projects like this:

====
include::sample[dir="snippets/fundamentals/developing-plugins/precompiledScriptPlugins-inBuildSrc/kotlin", files="build.gradle.kts[]"]
include::sample[dir="snippets/fundamentals/developing-plugins/precompiledScriptPlugins-inBuildSrc/groovy", files="build.gradle[]"]
====

[[sec:structuring_precompiled_plugins]]
== Structuring Precompiled Script Plugins

Precompiled script plugins are typically placed in either:

1. A dedicated `buildSrc` directory in your build, or
2. A separate included build (often named `build-logic`).

=== 1. Using `buildSrc`

**Precompiled script plugins** or **convention plugins** will often be found in the special `buildSrc` directory:

====
[.multi-language-sample]
=====
[source, kotlin]
----
.
└── buildSrc
    ├── build.gradle.kts
    └── src
       └── main
          └── kotlin
             └── myproject.java-conventions.gradle.kts
----
=====
[.multi-language-sample]
=====
[source, groovy]
----
.
└── buildSrc
    ├── build.gradle
    └── src
       └── main
          └── groovy
             └── myproject.java-conventions.gradle
----
=====
====

=== 2. Using a Composite Build

**Precompiled script plugins** or **convention plugins** will often be found in a <<composite_builds.adoc#defining_composite_builds,Composite Build>> with a name similar to `build-logic`:

====
[.multi-language-sample]
=====
[source, kotlin]
----
build-logic
├── settings.gradle.kts
├── build.gradle.kts
└── src
   └── main
      └── kotlin
         └── myproject.java-conventions.gradle.kts
----
=====
[.multi-language-sample]
=====
[source, groovy]
----
build-logic
├── settings.gradle
├── build.gradle
└── src
   └── main
      └── groovy
         └── myproject.java-conventions.gradle
----
=====
====

[[sec:applying_precompiled_plugin]]
== Applying a Precompiled Script Plugin

You apply a precompiled script plugin using its ID, derived from the script filename (excluding the `.gradle.kts` or `.gradle` extension).

====
[.multi-language-sample]
=====
[source, kotlin]
----
plugins {
    id("myproject.java-conventions")
}
----
=====
[.multi-language-sample]
=====
[source, groovy]
----
plugins {
    id("myproject.java-conventions")
}
----
=====
====

The script itself acts as the plugin.
There is no need to explicitly implement the link:{javadocPath}/org/gradle/api/Plugin.html[`Plugin`] interface; a requirement for binary plugins.

[[sec:publishing_precompiled_plugin]]
== Publishing a Precompiled Script Plugin

You can publish a precompiled script plugin to a repository, either a public one such as the https://plugins.gradle.org/[Gradle Plugin Portal], or a private artifact repository like Maven, Artifactory, or Nexus.

However, publishing precompiled script plugins is *not recommended* (they are meant for internal use only).
To publish them, you should first convert the precompiled script plugin into a binary plugin.

[[example_precompiled_script_plugin]]
== Example of a Precompiled Script Plugin

Let’s walk through creating a simple convention plugin using a precompiled script plugin in `buildSrc`.

=== 1. Create a `buildSrc` directory

In the root of your project, add a `buildSrc` directory:

====
[.multi-language-sample]
=====
[source, kotlin]
----
.   // root project
├── ...     // other project dirs and files
└── buildSrc
    ├── build.gradle.kts
    └── src
       └── main
          └── kotlin
----
=====
[.multi-language-sample]
=====
[source, groovy]
----
.   // root project
├── ...     // other project dirs and files
└── buildSrc
    ├── build.gradle
    └── src
       └── main
          └── groovy
----
=====
====

=== 2. Add a build file

Create `buildSrc/build.gradle.kts` with the supporting build logic your convention plugin will need to compile:

====
include::sample[dir="snippets/fundamentals/developing-plugins/testReport/kotlin", files="buildSrc/build.gradle.kts[]"]
include::sample[dir="snippets/fundamentals/developing-plugins/testReport/groovy", files="buildSrc/build.gradle[]"]
====

=== 3. Create a plugin script

Inside `buildSrc/src/main/kotlin` or `buildSrc/src/main/groovy`, write your convention plugin as a `.gradle(.kts)` file:

[source,text]
----
.
└── buildSrc
    ├── build.gradle.kts
    └── src
       └── main
          └── kotlin
             └── myproject.java-conventions.gradle.kts
----

In this example, the `myproject.java-conventions.gradle(.kts)` file contains the following code:

====
include::sample[dir="snippets/fundamentals/developing-plugins/testReport/kotlin", files="buildSrc/src/main/kotlin/myproject.java-conventions.gradle.kts[]"]
include::sample[dir="snippets/fundamentals/developing-plugins/testReport/groovy", files="buildSrc/src/main/groovy/myproject.java-conventions.gradle[]"]
====

The name of the script (`myproject.java-conventions.gradle(.kts)`) becomes the plugin ID: `myproject.java-conventions`.

=== 4. Apply the plugin in your project

In the `build.gradle(.kts)` of a consuming project, apply the plugin:

====
include::sample[dir="snippets/fundamentals/developing-plugins/testReport/kotlin", files="core/build.gradle.kts[]"]
include::sample[dir="snippets/fundamentals/developing-plugins/testReport/groovy", files="core/build.gradle[]"]
====

[.text-right]
**Next Step:** <<binary_plugin_advanced.adoc#binary_plugins_advanced,Learn about Binary Plugins>> >>
