O que é Gradle Plugin em Kotlin?

Um Gradle Plugin é um modulo que estende as capacidades do sistema de build Gradle, adicionando tarefas, configurações e convenções ao projeto. No ecossistema Kotlin, o plugin mais importante é o Kotlin Gradle Plugin (org.jetbrains.kotlin.jvm, org.jetbrains.kotlin.multiplatform, etc.), que ensina o Gradle a compilar código Kotlin.

Alem do plugin oficial do Kotlin, existem dezenas de plugins que automatizam tarefas comuns: serialização, geracaco de código, análise estática, publicacao de bibliotecas é muito mais.

Aplicando o Kotlin Gradle Plugin

A forma moderna de aplicar plugins usa o bloco plugins no build.gradle.kts:

plugins {
    kotlin("jvm") version "1.9.22"
}

repositories {
    mavenCentral()
}

dependencies {
    implementation(kotlin("stdlib"))
    testImplementation(kotlin("test"))
}

Para projetos Android:

plugins {
    id("com.android.application")
    kotlin("android") version "1.9.22"
}

Para projetos multiplataforma:

plugins {
    kotlin("multiplatform") version "1.9.22"
}

kotlin {
    jvm()
    iosArm64()
    iosSimulatorArm64()

    sourceSets {
        commonMain.dependencies {
            implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
        }
    }
}

Plugins comuns no ecossistema Kotlin

O ecossistema Kotlin tem vários plugins essenciais:

plugins {
    kotlin("jvm") version "1.9.22"
    kotlin("plugin.serialization") version "1.9.22" // kotlinx.serialization
    id("com.google.devtools.ksp") version "1.9.22-1.0.17" // KSP
    id("org.jetbrains.compose") version "1.5.12" // Compose Multiplatform
}

Cada plugin adiciona funcionalidades específicas:

  • kotlin-serialization: gera código de serialização em tempo de compilação.
  • KSP (Kotlin Symbol Processing): processa anotações e gera código.
  • Compose: habilita o compilador do Jetpack Compose.

Criando um Gradle Plugin customizado

Você pode criar seus próprios plugins para automatizar tarefas específicas do projeto. A forma mais simples e um plugin no buildSrc:

// buildSrc/src/main/kotlin/MeuPlugin.kt
import org.gradle.api.Plugin
import org.gradle.api.Project

class MeuPlugin : Plugin<Project> {
    override fun apply(projeto: Project) {
        projeto.tasks.register("saudacao") {
            group = "custom"
            description = "Exibe uma saudacao"
            doLast {
                println("Ola do MeuPlugin!")
            }
        }
    }
}
// buildSrc/build.gradle.kts
plugins {
    `kotlin-dsl`
}

repositories {
    mavenCentral()
}
// build.gradle.kts (no projeto principal)
plugins {
    id("meu-plugin") // Registrado automaticamente pelo buildSrc
}

Plugin com extension (configuração customizada)

Plugins mais sofisticados usam extensions para permitir configuração:

// Definir a extension
open class MinhaConfiguracao {
    var nomeDoApp: String = "MeuApp"
    var versao: String = "1.0.0"
    var habilitarLogs: Boolean = false
}

class PluginConfiguravelPlugin : Plugin<Project> {
    override fun apply(projeto: Project) {
        val config = projeto.extensions.create("minhaConfig", MinhaConfiguracao::class.java)

        projeto.afterEvaluate {
            projeto.tasks.register("info") {
                doLast {
                    println("App: ${config.nomeDoApp}")
                    println("Versão: ${config.versao}")
                    println("Logs: ${config.habilitarLogs}")
                }
            }
        }
    }
}

Uso no build.gradle.kts:

minhaConfig {
    nomeDoApp = "KotlinBrasil"
    versao = "2.0.0"
    habilitarLogs = true
}

Convention Plugins

Uma prática moderna e criar convention plugins que padronizam configurações em projetos multi-modulo:

// build-logic/convention/src/main/kotlin/kotlin-library-convention.gradle.kts
plugins {
    kotlin("jvm")
}

kotlin {
    jvmToolchain(17)
}

tasks.withType<Test> {
    useJUnitPlatform()
}

dependencies {
    testImplementation(kotlin("test"))
}
// Qualquer modulo do projeto
plugins {
    id("kotlin-library-convention")
}
// Automaticamente herda todas as configurações do convention plugin

Isso evita duplicacao de configuração entre modulos e garante consistencia.

Version Catalogs com plugins

O Gradle Version Catalog centraliza versões de dependências e plugins:

# gradle/libs.versions.toml
[versions]
kotlin = "1.9.22"
ksp = "1.9.22-1.0.17"

[plugins]
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
// build.gradle.kts
plugins {
    alias(libs.plugins.kotlin.jvm)
    alias(libs.plugins.kotlin.serialization)
}

Quando usar Gradle Plugins

  • Compilação de Kotlin: o plugin kotlin-jvm ou kotlin-multiplatform e obrigatório para compilar Kotlin.
  • Geracao de código: plugins como KSP e serialization geram código em tempo de compilação, evitando boilerplate.
  • Padronizacao: convention plugins garantem que todos os modulos de um projeto seguem as mesmas regras.
  • Automação: tarefas repetitivas como publicacao, geracao de documentação e análise de código podem ser automatizadas com plugins.
  • Integração: plugins conectam o build a ferramentas externas como Docker, Kubernetes, AWS.

Casos de Uso no Mundo Real

  1. configuração padronizada em projetos multi-modulo: empresas com dezenas de modulos Kotlin usam convention plugins para garantir que todos os modulos compartilhem a mesma versão do JDK, as mesmas regras de compilação e as mesmas dependências de teste. Isso elimina duplicacao de configuração e reduz erros causados por inconsistencias entre modulos.

  2. Geracao automatica de código com KSP: projetos que usam bibliotecas como Room, Moshi ou Hilt aplicam o plugin KSP para processar anotacoes e gerar código em tempo de compilação. O plugin elimina boilerplate manual e garante que o código gerado esteja sempre sincronizado com as definicoes das anotacoes.

  3. Pipeline de CI/CD com publicacao automatizada: plugins customizados automatizam o processo de versionamento, geracao de changelogs e publicacao de artefatos no Maven Central ou em repositórios privados. Um único comando ./gradlew publish executa todo o pipeline configurado pelo plugin.

  4. Analise estática e qualidade de código: plugins como Detekt e Ktlint sao aplicados para impor regras de estilo e detectar problemas de código em tempo de build. Eles podem ser configurados para falhar o build quando violacoes criticas sao encontradas, garantindo a qualidade do código antes do merge.

Boas Praticas

  • Utilize Version Catalogs (libs.versions.toml) para centralizar todas as versões de plugins e dependências em um único arquivo. Isso facilita atualizações e garante consistencia entre modulos do projeto.
  • Crie convention plugins no diretorio build-logic para configuracoes reutilizaveis em vez de duplicar blocos de configuração em cada build.gradle.kts. Isso segue o princípio DRY e facilita a manutenção.
  • Verifique a matriz de compatibilidade entre versões do Kotlin Gradle Plugin, KSP e outros plugins antes de atualizar. Incompatibilidades entre versões sao uma das causas mais frequentes de falhas de build.
  • Habilite o build cache e a compilação incremental do Kotlin para acelerar builds. Configure kotlin.incremental=true e org.gradle.caching=true no gradle.properties.
  • Prefira a DSL plugins {} com type-safe accessors em vez da sintaxe legada apply plugin. A DSL moderna oferece autocompletar no IDE, verificação de tipos e melhor legibilidade.

Perguntas Frequentes

P: Qual a diferenca entre um plugin aplicado com kotlin("jvm") e id("org.jetbrains.kotlin.jvm")? R: Sao equivalentes. A função kotlin("jvm") e um atalho (sugar syntax) fornecido pelo Gradle que se expande para id("org.jetbrains.kotlin.jvm"). Ambas as formas aplicam exatamente o mesmo plugin. A forma curta e mais legivel e preferida pela comunidade.

P: Quando devo criar um plugin customizado em vez de usar scripts de build? R: Crie um plugin customizado quando a lógica de build precisa ser reutilizada em múltiplos projetos ou modulos, quando a configuração e complexa o suficiente para se beneficiar de testes unitarios, ou quando você quer distribuir a lógica como um artefato independente. Para lógica simples e específica de um projeto, scripts no buildSrc ou build-logic sao suficientes.

P: O que e buildSrc e como ele se compara a build-logic? R: O buildSrc e um diretorio especial reconhecido automaticamente pelo Gradle, cujo código e compilado antes de qualquer script de build. O build-logic (ou build-conventions) e um included build configurado manualmente que oferece mais flexibilidade, como a possibilidade de cachear a compilação e evitar invalidacao de todo o build quando o código muda. Projetos modernos preferem build-logic com included builds.

P: Como posso depurar problemas causados por plugins do Gradle? R: Use ./gradlew build --info ou --debug para logs detalhados. O comando ./gradlew buildEnvironment mostra todos os plugins aplicados e suas versões. Para conflitos de dependência, ./gradlew dependencies exibe a arvore completa. Tambem e possível executar o build com --scan para gerar um relatorio interativo no Gradle Build Scan.

Erros comuns

  1. Versão incompativel entre plugins: o Kotlin Gradle Plugin, KSP e outros plugins precisam ter versões compatíveis. Verifique a matriz de compatibilidade antes de atualizar.

  2. Aplicar plugins na ordem errada: em projetos Android, o plugin Android deve ser aplicado antes do Kotlin. A ordem dos plugins pode afetar o comportamento do build.

  3. Usar apply em vez de plugins: a sintaxe antiga apply plugin: 'kotlin' ainda funciona, mas a DSL plugins { } e type-safe e preferida.

  4. Configurar o plugin fora do bloco correto: cada plugin tem seu bloco de configuração específico. Configurar no lugar errado causa erros silenciosos ou inesperados.

  5. Nao cachear builds: o Kotlin Gradle Plugin suporta incremental compilation e build cache. Nao configurar isso pode deixar o build muito mais lento do que necessário.

Tarefas úteis do Kotlin Gradle Plugin

# Compilar o projeto
./gradlew compileKotlin

# Executar testes
./gradlew test

# Verificar dependências
./gradlew dependencies

# Limpar e reconstruir
./gradlew clean build

Termos relacionados

  • KSP (Kotlin Symbol Processing): plugin para processamento de anotações e geracao de código em Kotlin.
  • Kotlin Multiplatform: plugin que habilita compilação para múltiplas plataformas.
  • Serialization: plugin que gera serializadores em tempo de compilação.
  • buildSrc: diretorio especial do Gradle para lógica de build compartilhada.
  • Version Catalog: sistema de gerenciamento centralizado de versões de dependências e plugins.
  • Convention Plugin: plugin que padroniza configurações entre modulos de um projeto.

Gradle Plugins são a espinha dorsal do sistema de build no ecossistema Kotlin. Entender como aplica-los, configura-los e, quando necessário, cria-los, e uma habilidade essencial para qualquer desenvolvedor Kotlin que trabalhe em projetos profissionais.