---
title: "Gradle com Kotlin DSL Tutorial em Português — Passo a Passo | Kotlin Brasil"
url: "https://kotlin.dev.br/tutoriais/kotlin-gradle-tutorial/"
markdown_url: "https://kotlin.dev.br/tutoriais/kotlin-gradle-tutorial.MD"
description: "Aprenda Gradle com Kotlin DSL: configure build.gradle.kts, dependências, plugins, multi-module e version catalogs. Tutorial completo em PT-BR."
date: "2025-07-22"
author: "Karina Melo"
---

# Gradle com Kotlin DSL Tutorial em Português — Passo a Passo | Kotlin Brasil

Aprenda Gradle com Kotlin DSL: configure build.gradle.kts, dependências, plugins, multi-module e version catalogs. Tutorial completo em PT-BR.


O **Gradle** é o sistema de build padrão para projetos Kotlin e Android, e quando combinado com o **Kotlin DSL** (arquivos `.kts`), oferece autocompletion, verificação de tipos em tempo de compilação e toda a expressividade da linguagem. Neste tutorial, vamos explorar desde a configuração básica do `build.gradle.kts` até tópicos avançados como projetos multi-módulo, version catalogs e criação de tasks customizadas.

## Por que Kotlin DSL no Gradle?

Tradicionalmente, arquivos Gradle usam Groovy, uma linguagem dinâmica sem verificação de tipos. Com Kotlin [DSL](/glossario/dsl/), você ganha suporte completo do IDE — autocompletion, navegação para definições, refatoração e erros em tempo de compilação. Como o arquivo de build é Kotlin puro, você pode usar [funções](/glossario/fun/), [classes](/glossario/class/), condicionais e tudo que a linguagem oferece diretamente na configuração.

## Passo 1: Estrutura Básica do build.gradle.kts

Vamos começar com a estrutura fundamental de um projeto Kotlin com Gradle:

```kotlin
// build.gradle.kts
plugins {
    kotlin("jvm") version "2.0.0"
    application
}

group = "com.exemplo"
version = "1.0.0"

application {
    mainClass.set("com.exemplo.MainKt")
}

repositories {
    mavenCentral()
    google()
}

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1")
    implementation("io.ktor:ktor-server-core:2.3.12")

    testImplementation(kotlin("test"))
    testImplementation("org.junit.jupiter:junit-jupiter:5.10.3")
}

tasks.test {
    useJUnitPlatform()
}

kotlin {
    jvmToolchain(21)
}
```

Cada seção tem uma responsabilidade clara: `plugins` ativa funcionalidades, `repositories` define de onde baixar dependências, `dependencies` lista as bibliotecas necessárias, e `kotlin` configura o compilador.

## Passo 2: Gerenciando Dependências

No Gradle, as dependências são organizadas por **configurações** que definem quando e como elas são usadas:

```kotlin
dependencies {
    // Disponível em compile-time e runtime
    implementation("com.squareup.okhttp3:okhttp:4.12.0")

    // Disponível em compile-time, mas nao exposta para consumidores
    implementation("com.google.code.gson:gson:2.11.0")

    // Exposta para consumidores da sua biblioteca
    api("org.jetbrains.exposed:exposed-core:0.52.0")

    // Apenas em compile-time (ex: processadores de annotation)
    compileOnly("org.projectlombok:lombok:1.18.34")

    // Apenas em runtime
    runtimeOnly("org.postgresql:postgresql:42.7.3")

    // Apenas para testes
    testImplementation("io.mockk:mockk:1.13.12")

    // Plataforma (BOM) para alinhar versoes
    implementation(platform("io.ktor:ktor-bom:2.3.12"))
    implementation("io.ktor:ktor-server-core")  // versao vem do BOM
}
```

A diferença entre `implementation` e `api` é crucial em projetos multi-módulo: `api` expõe a dependência para quem consome seu módulo, enquanto `implementation` a mantém privada. Sempre prefira `implementation` para reduzir o classpath transitivo.

## Passo 3: Plugins

Plugins estendem as capacidades do Gradle. Há duas formas de aplicá-los:

```kotlin
// build.gradle.kts
plugins {
    // Plugin do repositório de plugins do Gradle
    kotlin("jvm") version "2.0.0"
    kotlin("plugin.serialization") version "2.0.0"

    // Plugin por ID
    id("com.github.johnrengelman.shadow") version "8.1.1"

    // Plugin built-in do Gradle (sem versao)
    application
    `java-library`
}
```

Para projetos multi-módulo, defina versões de plugins uma única vez no `settings.gradle.kts`:

```kotlin
// settings.gradle.kts
pluginManagement {
    plugins {
        kotlin("jvm") version "2.0.0"
        kotlin("plugin.serialization") version "2.0.0"
    }
}
```

Depois, nos módulos, aplique sem especificar versão:

```kotlin
// modulo/build.gradle.kts
plugins {
    kotlin("jvm")
}
```

## Passo 4: Criando Tasks Customizadas

Tasks são a unidade fundamental de trabalho no Gradle. Você pode criar tasks personalizadas usando Kotlin:

```kotlin
// build.gradle.kts
tasks.register("gerarRelatorio") {
    group = "documentacao"
    description = "Gera relatório de dependências do projeto"

    doLast {
        val arquivo = file("$buildDir/relatorio.txt")
        arquivo.parentFile.mkdirs()

        val dependências = configurations["runtimeClasspath"]
            .resolvedConfiguration
            .resolvedArtifacts
            .map { "${it.moduleVersion.id}" }
            .sorted()

        arquivo.writeText(dependências.joinToString("\n"))
        println("Relatório gerado em: ${arquivo.absolutePath}")
    }
}

tasks.register<Copy>("copiarConfiguracoes") {
    from("src/main/resources/config")
    into("$buildDir/config")
    include("*.yaml", "*.properties")
    filter { linha -> linha.replace("localhost", System.getenv("DB_HOST") ?: "localhost") }
}
```

Tasks tipadas como `Copy`, `Jar`, `Exec` oferecem APIs específicas. Para criar tasks reutilizáveis com lógica complexa, use classes:

```kotlin
abstract class GerarDocTask : DefaultTask() {
    @get:Input
    abstract val modulo: Property<String>

    @get:OutputDirectory
    abstract val saida: DirectoryProperty

    @TaskAction
    fun executar() {
        val dir = saida.get().asFile
        dir.mkdirs()
        File(dir, "docs.txt").writeText("Documentação do módulo: ${modulo.get()}")
    }
}

tasks.register<GerarDocTask>("gerarDoc") {
    modulo.set("core")
    saida.set(layout.buildDirectory.dir("docs"))
}
```

## Passo 5: Projetos Multi-Módulo

Projetos grandes se beneficiam de uma arquitetura modular. Veja a estrutura típica:

```kotlin
// settings.gradle.kts
rootProject.name = "meu-projeto"

include(":core")
include(":api")
include(":app")
```

Cada módulo tem seu próprio `build.gradle.kts` e pode depender de outros:

```kotlin
// api/build.gradle.kts
plugins {
    kotlin("jvm")
}

dependencies {
    implementation(project(":core"))
    implementation("io.ktor:ktor-server-core:2.3.12")
}
```

Para compartilhar configurações entre módulos, use `subprojects` ou `allprojects` no build raiz:

```kotlin
// build.gradle.kts (raiz)
subprojects {
    apply(plugin = "org.jetbrains.kotlin.jvm")

    repositories {
        mavenCentral()
    }

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

    tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
        compilerOptions {
            jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21)
        }
    }
}
```

## Passo 6: Version Catalogs

O **Version Catalog** (introduzido no Gradle 7.0) centraliza todas as versões de dependências em um único arquivo TOML:

```kotlin
// gradle/libs.versions.toml
[versions]
kotlin = "2.0.0"
ktor = "2.3.12"
exposed = "0.52.0"
coroutines = "1.8.1"
junit = "5.10.3"

[libraries]
ktor-server-core = { module = "io.ktor:ktor-server-core", version.ref = "ktor" }
ktor-server-netty = { module = "io.ktor:ktor-server-netty", version.ref = "ktor" }
exposed-core = { module = "org.jetbrains.exposed:exposed-core", version.ref = "exposed" }
exposed-dao = { module = "org.jetbrains.exposed:exposed-dao", version.ref = "exposed" }
coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" }

[bundles]
ktor-server = ["ktor-server-core", "ktor-server-netty"]
exposed = ["exposed-core", "exposed-dao"]

[plugins]
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
```

No `build.gradle.kts`, use as referências tipadas:

```kotlin
dependencies {
    implementation(libs.coroutines.core)
    implementation(libs.bundles.ktor.server)
    implementation(libs.bundles.exposed)
    testImplementation(libs.junit.jupiter)
}
```

O Version Catalog gera acessors type-safe, então o IDE oferece autocompletion completo. Bundles agrupam dependências relacionadas, simplificando a declaração em múltiplos módulos.

## Passo 7: buildSrc para Lógica Compartilhada

O diretório `buildSrc/` é compilado automaticamente pelo Gradle e disponibilizado em todos os scripts de build. Use-o para convention plugins e constantes:

```kotlin
// buildSrc/build.gradle.kts
plugins {
    `kotlin-dsl`
}

repositories {
    mavenCentral()
}
```

```kotlin
// buildSrc/src/main/kotlin/kotlin-conventions.gradle.kts
plugins {
    kotlin("jvm")
}

group = "com.exemplo"

repositories {
    mavenCentral()
}

kotlin {
    jvmToolchain(21)
}

tasks.test {
    useJUnitPlatform()
}
```

Depois, aplique em qualquer módulo:

```kotlin
// core/build.gradle.kts
plugins {
    id("kotlin-conventions")
}

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1")
}
```

O `buildSrc` é excelente para eliminar duplicação entre módulos. Para projetos muito grandes, considere migrar para **Composite Builds** com convention plugins em um diretório separado como `build-logic/`.

## Erros Comuns

**1. Misturar sintaxe Groovy com Kotlin DSL:** Strings com aspas simples (`'valor'`) não existem em Kotlin. Use sempre aspas duplas. Atribuições com `=` são obrigatórias no Kotlin DSL (Groovy permite omitir).

**2. Não usar `kotlin("test")` para testes:** Essa dependência inclui automaticamente as assertions do Kotlin e o adapter correto para a plataforma. Sem ela, você precisa importar assertions do JUnit diretamente.

**3. Esquecer `useJUnitPlatform()`:** Sem essa configuração na task `test`, o Gradle não encontra nem executa os testes JUnit 5. Esse é um dos erros mais frustrantes para iniciantes.

**4. Version Catalog com nomes inválidos:** No TOML, use hífens nos nomes de bibliotecas. O Gradle converte para pontos nos acessors Kotlin (ex: `ktor-server-core` vira `libs.ktor.server.core`).

**5. buildSrc recriando cache a cada mudança:** Qualquer alteração no `buildSrc` invalida todo o cache do Gradle. Para projetos grandes, prefira Composite Builds que oferecem invalidação granular.

## Conclusão e Próximos Passos

Neste tutorial, exploramos o Gradle com Kotlin DSL de ponta a ponta: desde a estrutura básica do `build.gradle.kts` até técnicas avançadas como version catalogs, projetos multi-módulo e buildSrc. Dominar o Gradle é essencial para qualquer desenvolvedor Kotlin, pois o sistema de build impacta diretamente a produtividade e manutenibilidade do projeto.

Como próximos passos, estude o **Gradle Configuration Cache** para builds mais rápidos, explore plugins como **Shadow** para fat JARs e **Detekt** para análise estática de código Kotlin. Para aprofundar seu conhecimento em Kotlin [DSL](/glossario/dsl/), confira nosso tutorial dedicado sobre [como criar DSLs em Kotlin](/tutoriais/kotlin-dsl-tutorial/).
