ÖNEMLİ : Kendim için aldığım notlar. Umarım size de bir faydası olur. Bu yazı Jendrik Johannes’in Gradle’ı Anlamak İsimli Youtube içeriklerinin bir çevirisidir ve yazarın izni alınarak paylaşılmaktadır. Amacım hem aldığım notları sizinle paylaşmak hem de bilmeyenler için Jendrik’i size tanıtmaktır. Jendrik’in Gradle ile ilgili çok değerli içeriklere sahip olduğunu düşünüyorum. Türkçe kaynağa destek olmak için bu çevirileri sizinle paylaşmak istedim. Aşağıdaki yazı Jendrik’in kendi cümleleri olup, sadece turuncu blok içerisinde öne çıkardığım notlar bana aittir. Referanslara ise sayfa sonundan ulaşabilirsiniz.

Serinin Diğer İçerikleri:


Diğer içerikleri görüntülemek için linke tıklayın.

Build Dosyaları (central configuration scripts of Gradle)

Bu yazıda Gradle’ın en merkezi yapılandırma betiklerinden (script), build dosyalarından bahsedeceğiz. Bir build dosyası, groovy DSL için build.gradle veya kotlin DSL için build.gradle.kts olarak adlandırılır.

Benim Notum: Domain-Specific Language (DSL) nedir?


Domain-Specific Language (DSL), her türlü yazılım sorununu amaçlayan genel amaçlı bir dil yerine (örneğin java gibi), belirli bir tür sorunu hedefleyen bir bilgisayar dilidir. 1 Kotlin ve Groovy dilleri de JVM üzerine inşa edilmiş birer DSL’dir.

gradle'ı anlamak (understanding gradle) build file


Her alt projeye boş bir build dosyası ekleyin

Önceki bölümde üç tane alt proje (subproject) oluşturmuştuk. Biri etki alanı modelimiz için (domain-model), biri iş mantığımız için (business-logic) ve biri de uygulama kodumuz için (application code)‘du. Şu ana kadar bu alt projeler boş ve dolayısıyla Gradle için gerçek bir anlam taşımıyor. Bunu değiştirmek için her birine bir build dosyası ekleyebiliriz.

gradle'ı anlamak (understanding gradle) add build file to each subproject


Ayrıntılar için business-logic projesinin “build dosyasına” bir bakalım. Build dosyalarınızda yapılandırılacak üç şey vardır.

1 - Bir alt projeye anlam katın - bir plugin uygulayın


build.gradle.kts

1
2
3
plugins{
    id("java-library")
}

İlk şey, plugin{} bloğunda uyguladığınız eklentilerdir. Bir eklenti (plugin) uygulayarak alt projenize yapı ve anlam kazandırırsınız. projeyi inşa etmesi için gradle’ın bilmesi gereken her şey budur. Örnekte, gradle ile birlikte gelen Java kütüphane eklentisini (java-library) uyguluyoruz.

gradle'ı anlamak (understanding gradle) apply plugins to each subproject


Benim Notum: java-library plugin ile java plugin arasındaki fark nedir?


“Java plugin” (java), bir projeye test etme ve paketleme yeteneklerinin yanı sıra Java derlemesi ekler. Diğer birçok JVM dili Gradle eklentisinin temelini oluşturur.

1
2
3
4
5
6
7
8
9
//Kotlin
plugins {
    java
}

// Groovy
plugins {
    id 'java'
}

“Java Library plugin” (java-library), Java kitaplıkları (java libraries) hakkında özel bilgi sağlayarak “Java plugin”inin (java) yeteneklerini genişletir. Özellikle bir “Java library” tüketicilere bir “API” sunar (yani, Java veya Java Library plugin’i kullanan diğer projeler). “Java plugin” tarafından sunulan tüm kaynak kümeleri(source sets), görevler (tasks) ve konfigürasyonlar, bu eklenti kullanıldığında dolaylı olarak mevcuttur.

1
2
3
4
5
6
7
8
9
//Kotlin
plugins {
    `java-library`
}

// Groovy
plugins {
    id 'java-library'
}

Uygulanan bu eklenti (plugin) alt projeyi bir Java kütüphane projesine dönüştürür, böylece gradle, ayrıca IDE, kaynak kodun nerede bulunduğunu, kodun nasıl derlendiğini ve bir jar dosyasına nasıl paketlendiğini bilir.

2 - Extension aracılığıyla eklentinin (plugin) ayrıntılarını yapılandırın


1
2
3
java {
    toolchain.languageVersion.set(JavaLanguageVersion.of(11))
}

Bazen Java derlemesinin (java compilation) belirli ayrıntılarını yapılandırmak isteyebilirsiniz. Bu tür şeyler için eklentiler (plugins) uzantı (extension) adı verilen şeyler sağlar. Bizim durumumuzda Java uzantısına (java extension) (aşağıdaki gibi) erişebiliyoruz. Dolayısıyla uzantılar (extension), build dosyalarında yapılandırılacak ikinci şeydir. Burada, hedeflemek istediğimiz Java sürümünü yapılandırmak için kullanıyoruz.

gradle'ı anlamak (understanding gradle) Configure details of plugin through an extension


Benim Notum: Set properties


Bir plugin, uzantıları (extension) kullanarak bir projeye özellikler (properties) ve metotlar ekleyebilir.

Project nesnesi, projeye uygulanan eklentilerin tüm ayarlarını (settings) ve özelliklerini (properties) içeren ilişkili bir ExtensionContainer nesnesine sahiptir. 2

Örneğin; application eklentisi, Java uygulamamızın main sınıfını detaylandırmak için kullanılan bir application özelliği ekler:

1
2
3
application {
  mainClass = "com.example.Main"
}

3 - Bağımlılıkları (dependencies) beyan etmek


Build dosyalarında yapılandırılacak üçüncü şey, alt projenizin bağımlılıklarıdır (dependencies). Yani, oluşturduğunuz bileşendir (component). Bağımlılıklar, binary depolar (repositories) veya diğer build’ler gibi başka yerlerden gelen diğer alt projeler veya bileşenler (components) olabilir. Örneğimizde biz, veri modeli (data-model) alt projesine ve harici (external) bir bileşen olan apache commons lang kütüphanesine bağlıyız.

gradle'ı anlamak (understanding gradle) Declare dependencies


1
2
3
4
dependencies {
    implementation(project(":data-model"))
    implementation("org.apache.commons:commons-lang3:3.9")
}

Diğer alt projelere project anahtar sözcüğü ve alt projenin adı kullanılarak atıfta bulunulur.

gradle'ı anlamak (understanding gradle) Declare dependencies - project keyword


Diğer bileşenlere ise grup, isim ve versiyondan oluşan koordinatlarıyla (aşağıdaki gibi) atıfta bulunulur.

gradle'ı anlamak (understanding gradle) Declare dependencies - Other components are referred to by their coordinates made up of group, name and version.


gradle'ı anlamak (understanding gradle) Declare dependencies - Other components are referred to by their coordinates made up of group, name and version.


gradle'ı anlamak (understanding gradle) Declare dependencies - Other components are referred to by their coordinates made up of group, name and version.


build.gradle.kts

1
2
3
4
5
6
7
8
9
10
11
12
plugins{
    id("java-library")
}

java {
    toolchain.languageVersion.set(JavaLanguageVersion.of(11))
}

dependencies {
    implementation(project(":data-model"))
    implementation("org.apache.commons:commons-lang3:3.9")
}

Burada kotlin dilinin tüm gücüne sahip olduğumuz için build dosyalarında çok daha fazla şey yapabiliriz. Ancak build’nizi iyi yapılandırılmış ve bakımı kolay tutmak için burada tartıştığımız üç konsepte bağlı kalmanızı tavsiye ederim. Diğer tüm build yapılandırmaları ve custom build mantığı eklentilere (plugin) girmelidir. Bunların ne zaman ve nasıl tanımlanacağı bir sonraki içerikte ele alınacaktır. Bunu akılda tutarak, build dosyalarının temelleriyle ilgili her şey budur.

Benim Notum: Project object


Hatırlarsanız settings script’inin Settings objesini yapılandırdığından bahsetmiştik. Benzer şekilde bir build scripti de bir projeyi yapılandırır ve Project türünde bir nesneyle ilişkilendirilir.

gradle'ı anlamak (understanding gradle) build script configures the Project object


build script yürütülürken, Project‘i yapılandırır. Bunun yanı sıra build script’i, Project nesnelerini ile beraber, onların alt öğelerini (children) de yapılandırır.

Project nesnesi Gradle API’sinin bir parçasıdır. Bu interface, build dosyanızdan Gradle ile etkileşim kurmak için kullandığınız ana API’dir. Bir Project‘den, Gradle’ın tüm özelliklerine programatik erişim vardır. Bir build script’indeki birçok üst düzey özellik ve blok, Project API’sinin bir parçasıdır.

Örneğin, aşağıdaki build script, projenin adını yazdırmak için Project.name özelliğini kullanır:

1
2
println(name)
println(project.name)
1
2
3
$ gradle -q check
project-api
project-api

Her iki println ifadesi de aynı özelliği yazdırır.

İlki, Project nesnesinin name özelliğine (property) üst düzey (top-level) referansı kullanır. İkinci ifade, ilişkili “Project” nesnesini döndüren herhangi bir build script için mevcut olan “proje” özelliğini (property) kullanır.

Standard project properties

Name Type Description
name String - Proje dizininin adı
path String - Projenin tam nitelikli adı (fully qualified name)
description String - Projenin açıklaması (description)
dependencies DependencyHandler - Projenin bağımlılık işleyicisini döndürür (dependency handler)
repositories RepositoryHandler - Projenin repo işleyicisini döndürür (repository handler)
layout ProjectLayout - Bir proje için birçok önemli konuma erişim sağlar. (access to several important locations)
group Object - Bu projenin grubu. (The group of this project.)
version Object - Bu projenin versiyonu. (The version of this project.)

Aşağıdaki tabloda yaygın olarak kullanılan birkaç yöntem listelenmektedir:

Name Description
uri() - Bu “projenin” proje dizinine göre bir “URI”ye giden dosya yolunu çözümler. (Resolves a file path to a “URI”, relative to the project directory of this “project”.)
task() - Verilen adla bir Görev oluşturur ve onu bu projeye ekler. (Creates a Task with the given name and adds it to this project.)

Benim Notum: Declare Variables


Build script’ler iki değişken bildirebilir: yerel değişkenler (local variables) ve ekstra özellikler(extra properties). 3

  • Local Variables

    Lokal değişkenleri val anahtar sözcüğüyle deklare edin. Yerel değişkenler yalnızca bildirildikleri kapsamda görünür. Bunlar temel Kotlin dilinin bir özelliğidir. Groovy için bu anahtar sözcük def dir.

    build.gradle.kts

    1
    2
    3
    4
    5
    6
    
      val dest = "dest"
        
      tasks.register<Copy>("copy") {
        from("source")
        into(dest)
      }
    
  • Extra Properties

    Gradle’ın projeler, görevler (tasks) ve kaynak kümeleri (source sets) dahil “enhanced (gelişmiş)” nesneleri, kullanıcı tanımlı özellikleri (user-defined properties) tutabilir.

    Sahip olunan nesnenin extra özelliği (property) aracılığıyla ekstra özellikler ekleyin (add), okuyun (read) ve ayarlayın (set). Alternatif olarak, extra seçeneğini kullanarak “Kotlin tarafından yetkilendirilmiş özellikler (Kotlin delegated properties)” aracılığıyla ekstra özelliklere erişebilirsiniz.

    build.gradle.kts

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    
      plugins {
        id("java-library")
      }
        
      val springVersion by extra("3.1.0.RELEASE")
      val emailNotification by extra { "[email protected]" }
        
      sourceSets.all { extra["purpose"] = null }
        
      sourceSets {
        main {
          extra["purpose"] = "production"
        }
        test {
          extra["purpose"] = "test"
        }
        create("plugin") {
          extra["purpose"] = "production"
        }
      }
        
      tasks.register("printProperties") {
        val springVersion = springVersion
        val emailNotification = emailNotification
        val productionSourceSets = provider {
          sourceSets.matching { it.extra["purpose"] == "production" }.map { it.name }
        }
        doLast {
          println(springVersion)
          println(emailNotification)
          productionSourceSets.get().forEach { println(it) }
        }
      }
    
    1
    2
    3
    4
    5
    
      $ gradle -q printProperties
      3.1.0.RELEASE
      [email protected]
      main
      plugin
    

    Bu örnek, “extra” yoluyla “project” nesnesine iki ekstra özellik ekler. Ek olarak, bu örnek, extra["purpose"]ı “null” olarak ayarlayarak her kaynak kümesine “purpose” adlı bir özellik ekler. Eklendikten sonra bu özellikleri “extra” aracılığıyla okuyabilir ve ayarlayabilirsiniz.

Referanslar:

Daha Fazla Okuma: