# Pre-compiled Script Plugins

version 9.4.1

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.

## 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:

buildSrc/src/main/kotlin/java-library-convention.gradle.kts

    plugins {
        `java-library`
        checkstyle
    }

    java {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
    }

    checkstyle {
        maxWarnings = 0
        // ...
    }

    tasks.withType<JavaCompile> {
        options.isWarnings = true
        // ...
    }

    dependencies {
        testImplementation("junit:junit:4.13")
        // ...
    }

buildSrc/src/main/groovy/java-library-convention.gradle

    plugins {
        id 'java-library'
        id 'checkstyle'
    }

    java {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
    }

    checkstyle {
        maxWarnings = 0
        // ...
    }

    tasks.withType(JavaCompile) {
        options.warnings = true
        // ...
    }

    dependencies {
        testImplementation("junit:junit:4.13")
        // ...
    }

And are applied in other projects like this:

build.gradle.kts

    plugins {
        `java-library-convention`
    }

build.gradle

    plugins {
        id 'java-library-convention'
    }

## 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:

    .
    └── buildSrc
        ├── build.gradle.kts
        └── src
           └── main
              └── kotlin
                 └── myproject.java-conventions.gradle.kts

    .
    └── 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 Build with a name similar to `build-logic`:

    build-logic
    ├── settings.gradle.kts
    ├── build.gradle.kts
    └── src
       └── main
          └── kotlin
             └── myproject.java-conventions.gradle.kts

    build-logic
    ├── settings.gradle
    ├── build.gradle
    └── src
       └── main
          └── groovy
             └── myproject.java-conventions.gradle

## 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).

    plugins {
        id("myproject.java-conventions")
    }

    plugins {
        id("myproject.java-conventions")
    }

The script itself acts as the plugin. There is no need to explicitly implement the `Plugin` interface; a requirement for binary plugins.

## Publishing a Precompiled Script Plugin

You can publish a precompiled script plugin to a repository, either a public one such as the 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 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:

    .   // root project
    ├── ...     // other project dirs and files
    └── buildSrc
        ├── build.gradle.kts
        └── src
           └── main
              └── kotlin

    .   // 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:

buildSrc/build.gradle.kts

    plugins {
        `kotlin-dsl`
    }

    repositories {
        gradlePluginPortal()
    }

buildSrc/build.gradle

    plugins {
        id 'groovy-gradle-plugin'
    }

    repositories {
        gradlePluginPortal()
    }

### 3. Create a plugin script

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

    .
    └── 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:

buildSrc/src/main/kotlin/myproject.java-conventions.gradle.kts

    plugins {
        id("java")
    }

    // Disable the test report for the individual test task
    tasks.named<Test>("test") {
        reports.html.required = false
    }

    // Share the test report data to be aggregated for the whole project
    configurations.create("binaryTestResultsElements") {
        isCanBeResolved = false
        isCanBeConsumed = true
        attributes {
            attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.DOCUMENTATION))
            attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named("test-report-data"))
        }
        outgoing.artifact(tasks.test.map { task -> task.getBinaryResultsDirectory().get() })
    }

    repositories {
        mavenCentral()
    }

buildSrc/src/main/groovy/myproject.java-conventions.gradle

    plugins {
        id 'java'
    }

    // Disable the test report for the individual test task
    test {
        reports.html.required = false
    }

    // Share the test report data to be aggregated for the whole project
    configurations {
        binaryTestResultsElements {
            canBeResolved = false
            canBeConsumed = true
            attributes {
                attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.DOCUMENTATION))
                attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType, 'test-report-data'))
            }
            outgoing.artifact(test.binaryResultsDirectory)
        }
    }

    repositories {
        mavenCentral()
    }

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:

core/build.gradle.kts

    plugins {
        id("myproject.java-conventions")
    }

    dependencies {
        testImplementation("junit:junit:4.13")
    }

core/build.gradle

    plugins {
        id 'myproject.java-conventions'
    }

    dependencies {
        testImplementation 'junit:junit:4.13'
    }

Next Step: Learn about Binary Plugins >>