Ö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.

TASKS (Görevler)

Önceki içeriklerde tanıttığımız örnek projeye geri dönelim. Bu sefer, task’ları çalıştırdığımız bir alt projeye örnek olarak “app” alt projesine odaklanacağız. Şu anda projenin build dosyası boş.

Boş Bir Projenin Görevleri Nelerdir? (Tasks of a plain/empty project)

Gradle’dan build’ları çalıştırmak için mevcut görevleri (tasks) bize göstermesini istersek, yalnızca birkaç help task’ının mevcut olduğunu görebiliriz.

gradle'ı anlamak (understanding gradle) tasks


gradle'ı anlamak (understanding gradle) tasks


Bunun nedeni, Gradle'ın çekirdeğinin yalnızca bu görevleri build'inizi analiz etmek için sağlamasıdır. Projenizi gerçekten oluşturmak için gereken diğer görevler(tasks) de pluginler tarafından eklenir.

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
 % gradle :app:tasks

> Task :app:tasks

------------------------------------------------------------
Tasks runnable from project ':app'
------------------------------------------------------------

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in project ':app'.
dependencies - Displays all dependencies declared in project ':app'.
dependencyInsight - Displays the insight into a specific dependency in project ':app'.
help - Displays a help message.
javaToolchains - Displays the detected java toolchains.
kotlinDslAccessorsReport - Prints the Kotlin code for accessing the currently available project extensions and conventions.
outgoingVariants - Displays the outgoing variants of project ':app'.
projects - Displays the sub-projects of project ':app'.
properties - Displays the properties of project ':app'.
resolvableConfigurations - Displays the configurations that can be resolved in project ':app'.
tasks - Displays the tasks runnable from project ':app'.

To see all tasks and more detail, run gradle tasks --all

To see more detail about a task, run gradle help --task <task>

Benim Notum : gradle tasks komutunda olduğu gibi ./gradlew tasks komutuyla da ilgili projenin görevlerini listeleyebilirsiniz. Aslında ./gradlew komutunu kullanmak çoklu projelerde versiyon tutarlılığını sağlamak için daha iyidir.

Benim Notum: Register and configure tasks:


gradle'ı anlamak (understanding gradle) tasks


Bir görev (task), bir build’in gerçekleştirdiği bazı bağımsız iş birimlerini temsil eder. Görevler (Tasks), sınıfların derlenmesi, JAR oluşturma, Javadoc oluşturma, birim testlerinin (unit tests) çalıştırılması veya bir WAR dosyasının sıkıştırılması (zipping up a WAR file) gibi bazı temel işleri gerçekleştirir. Görevler genellikle pluginlerde tanımlanmış olsa da, görevleri build script’lerde kaydetmeniz (register) veya yapılandırmanız gerekebilir. Özetle görevler ya build script’lerden ya da pluginlerden gelir. 1 2

Bir kullanıcı komut satırında ./gradlew build komutunu çalıştırdığında Gradle, build görevini, bağlı olduğu diğer görevlerle birlikte yürütür.

Bir görevin kaydedilmesi (registering), görevi projenize ekler.

TaskContainer.register(java.lang.String) yöntemini kullanarak görevleri bir projeye kaydedebilirsiniz:

1
2
3
4
5
6
tasks.register<Zip>("zip-reports") {
  from 'Reports/'
  include '*'
  archiveName 'Reports.zip'
  destinationDir(file('/dir'))
}

Kaçınılması gereken TaskContainer.create(java.lang.String) yönteminin kullanımını görmüş olabilirsiniz:

1
2
3
4
5
6
tasks.create<Zip>("zip-reports") {
  from 'Reports/'
  include '*'
  archiveName 'Reports.zip'
  destinationDir(file('/dir'))
}

Görev yapılandırmasından kaçınmayı sağlayan “register()”, “create()” yerine tercih edilir.

Yapılandırmak için bir görevin yerini “TaskCollection.named(java.lang.String)yöntemini kullanarak saptayabilirsiniz. İlgili görevi, oluşturulmasını veya yapılandırılmasını tetiklemeden ada (name) göre bulur; böyle bir nesne yoksa başarısız olur.

1
2
3
tasks.named<Test>("test") {
  useJUnitPlatform()
}

Aşağıdaki örnek, Javadoc görevini, Java kodundan otomatik olarak HTML belgeleri oluşturacak şekilde yapılandırır:

1
2
3
4
5
tasks.named("javadoc").configure {
  exclude 'app/Internal*.java'
  exclude 'app/internal/*'
  exclude 'app/internal/*'
}

Task registration and action

1
2
3
4
5
6
//build.gradle.kts
tasks.register("hello") {
  doLast {
    println("Hello world!")
  }
}

Örnekte, build script, TaskContainer API’yi kullanarak “hello” adlı tek bir görevi kaydeder (register) ve ona bir eylem (action) ekler. Aslında, TaskContainer, bir dizi Task örneğinin yönetilmesinden sorumludur. Bir TaskContainer örneğini Project.getTasks()‘ı çağırarak veya build script‘inizde tasks özelliğini (property) kullanarak elde edebilirsiniz. Bu link aracılığı ile tüm özellikleri (properties) görüntüleyebilirsiniz.

Projedeki görevler (tasks) listelenmişse, hello görevi Gradle tarafından kullanılabilir:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ ./gradlew app:tasks --all

> Task :app:tasks

------------------------------------------------------------
Tasks runnable from project ':app'
------------------------------------------------------------

Other tasks
-----------
compileJava - Compiles main Java source.
compileTestJava - Compiles test Java source.
hello
processResources - Processes main resources.
processTestResources - Processes test resources.
startScripts - Creates OS-specific scripts to run the project as a JVM application.

build script’deki görevi ./gradlew hello komutu ile yürütebilirsiniz:

1
2
$ ./gradlew hello
Hello world!

Gradle hello görevini yürüttüğünde, sağlanan eylemi (action) yürütür. Bu örnekte, eylem (action) basit bir kod içeren bir bloktur: println("Hello world!").

Task group and description

Az önce ele alınan hello görevi, bir açıklamayla (description) detaylandırılabilir ve aşağıdaki güncellemeyle bir gruba (group) atanabilir:

1
2
3
4
5
6
7
8
9
//build.gradle.kts

tasks.register("hello") {
  group = "Custom"
  description = "A lovely greeting task."
  doLast {
    println("Hello world!")
  }
}

Görev bir gruba atandığında “./gradlew tasks” tarafından listelenecektir.

1
2
3
4
5
6
7
$ ./gradlew tasks

> Task :tasks

Custom tasks
------------------
hello - A lovely greeting task.

Bir görevle ilgili bilgileri görüntülemek için “help --task <görev-adı>” komutunu kullanın:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$./gradlew help --task hello

> Task :help
Detailed task information for hello

Path
:app:hello

Type
Task (org.gradle.api.Task)

Options
--rerun     Causes the task to be re-run even if up-to-date.

Description
A lovely greeting task.

Group
Custom

Gördüğümüz gibi hello görevi custom grubuna aittir.

base Plugin kullanan bir projenin görevleri

Bazı merkezi yaşam döngüsü görevleri (central lifecycle tasks) ekleyen bir Gradle çekirdek (core) eklentisi olan ‘base’ plugini ekleyerek bunu keşfetmeye başlayalım.

1
2
3
plugins {
    id("base")
}
gradle'ı anlamak (understanding gradle) gradle base plugin tasks


gradle'ı anlamak (understanding gradle) gradle base plugin tasks


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
34
35
36
37
38
39
40
41
% gradle :app:tasks                                                         
Starting a Gradle Daemon (subsequent builds will be faster)

> Task :app:tasks

------------------------------------------------------------
Tasks runnable from project ':app'
------------------------------------------------------------

Build tasks
-----------
assemble - Assembles the outputs of this project.
build - Assembles and tests this project.
clean - Deletes the build directory.

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in project ':app'.
dependencies - Displays all dependencies declared in project ':app'.
dependencyInsight - Displays the insight into a specific dependency in project ':app'.
help - Displays a help message.
javaToolchains - Displays the detected java toolchains.
kotlinDslAccessorsReport - Prints the Kotlin code for accessing the currently available project extensions and conventions.
outgoingVariants - Displays the outgoing variants of project ':app'.
projects - Displays the sub-projects of project ':app'.
properties - Displays the properties of project ':app'.
resolvableConfigurations - Displays the configurations that can be resolved in project ':app'.
tasks - Displays the tasks runnable from project ':app'.

Verification tasks
------------------
check - Runs all checks.

Rules
-----
Pattern: clean<TaskName>: Cleans the output files of a task.
Pattern: build<ConfigurationName>: Assembles the artifacts of a configuration.

To see all tasks and more detail, run gradle tasks --all

To see more detail about a task, run gradle help --task <task>

Benim Notum:


Görüleceği üzere Help tasks‘lara ek olarak Build tasks, Verification tasks ve Rules‘un çıktıya eklendiğini görüyoruz. Bu ek görevler gradle core plugin olan “base” plugin aracılıyla gelmektedir.

Base Plugin”, çoğu “build” için ortak olan bazı görevleri ve “kuralları (conventions)” sağlar ve build’e bunların çalıştırılma şekli konusunda tutarlılığı destekleyen bir yapı (structure) ekler. En önemli katkısı, diğer eklentiler ve “build” yazarları tarafından sağlanan daha spesifik görevler için bir “şemsiye (umbrella)” görevi gören bir dizi “yaşam döngüsü görevleri”dir (lifecycle tasks).

Base plugin’in bir başka kullanımı da bu şekildedir.

1
2
3
4
5
6
7
8
// kotlin
plugins {
    base
}
// groovy
plugins {
    id 'base'
}

Tasks (Görevler)

  • clean — Delete “build” dizinini ve içindeki her şeyi, yani “layout.buildDirectory” proje özelliği tarafından belirtilen yolu (path) siler.
  • check — lifecycle task Pluginler ve “build” yazarları, testleri çalıştıranlar gibi doğrulama görevlerini “check.dependsOn(task)” kullanarak bu yaşam döngüsü görevine eklemelidir.
  • assemble — lifecycle task Pluginler ve “derleme” yazarları, bu “yaşam döngüsü (lifecycle)” görevine dağıtımlar (distributions) ve diğer tüketilebilir artifaktleri üreten görevleri eklemelidir. Örneğin, “jar”, Java kitaplıkları için tüketilebilir artifakt üretir. “assemble.dependsOn(task)” komutunu kullanarak görevleri bu yaşam döngüsü (lifecycle) görevine ekleyin.
  • build — lifecycle task (check ve assemble görevlerine bağlıdır.) Tüm testlerin yürütülmesi, üretim artifaktlerinin (production artifacts) üretilmesi ve belgelerin (documentation) oluşturulması da dahil olmak üzere her şeyin build edilmesi amaçlanmaktadır. “assemble” ve “check” tipik olarak daha uygun olduğundan, muhtemelen somut görevleri doğrudan build’e nadiren ekleyeceksiniz.
  • buildConfiguration — task rule İsimlendirilmiş konfigürasyona (named configuration) eklenen artifaktleri birleştirir. Örneğin, “buildRuntimeElements”, “runtimeElements” yapılandırmasına eklenen herhangi bir artifakti oluşturmak için gereken her görevi yürütecektir.
  • cleanTask — task rule Bir görevin tanımlanmış çıktılarını (defined outputs) kaldırır; ör. “cleanJar”, “Java Plugin”in “jar” görevi tarafından üretilen “JAR” dosyasını silecektir.

BAĞIMLILIK YÖNETİMİ (Dependency management)

“Base Plugin” bağımlılıklar (dependencies) için hiçbir yapılandırma eklemez ancak aşağıdaki yapılandırmaları ekler:

  • default “Bağımlılık çözümlemesi (dependency resolution)” istek öznitelikleri (request attributes) olmadan gerçekleştirildiğinde kullanılan bir “geri dönüş (fallback)” yapılandırmasıdır. Yeni build’ler ve plugin’ler, “default” yapılandırmayı kullanmamalıdır! Yalnızca geriye dönük uyumluluk (backwards compatibility) için varlığını sürdürür. Bağımlılık çözümlemesi (dependency resolution) istek öznitelikleriyle (request attributes) gerçekleştirilmelidir.
  • archivesarchives” yapılandırmasında tanımlanan tüm artifaktler, “assemble” görevi tarafından otomatik olarak oluşturulur (build edilir). Yeni “build’ler” ve “pluginler”, “archives” yapılandırmasını kullanmamalıdır! Yalnızca geriye dönük uyumluluk (backwards compatibility) için varlığını sürdürür. Bunun yerine, görev bağımlılıkları (task dependencies) doğrudan “assemble” görevinde bildirilmelidir.

KATKIDA BULUNAN UZANTILAR (Contributed extensions)

“Base Plugin”, projeye “baseuzantısını ekler. Bu, tahsis edilmiş (dedicated) bir DSL bloğu içinde aşağıdaki özelliklerin (properties) yapılandırılmasına olanak tanır.

build.gradle.kts

1
2
3
4
5
base {
    archivesName = "gradle"
    distsDirectory = layout.buildDirectory.dir("custom-dist")
    libsDirectory = layout.buildDirectory.dir("custom-libs")
}
  • archivesName — default: $project.namearchive” görevleri için varsayılan “AbstractArchiveTask.getArchiveBaseName()” değerini sağlar.
  • distsDirectory — default: layout.buildDirectory.dir(“distributions”) Dağıtım arşivlerinin (distribution archives), yani JAR olmayanların oluşturulduğu dizinin varsayılan adıdır.
  • libsDirectory — default: layout.buildDirectory.dir(“libs”) Kütüphane arşivlerinin (library archives), yani JAR’ların oluşturulduğu dizinin varsayılan adıdır.

Plugin ayrıca “AbstractArchiveTask“ı genişleten herhangi bir görevde (task) aşağıdaki özellikler (properties) için varsayılan değerler sağlar:

  • destinationDirectory JAR olmayan arşivler (non-JAR archives) için varsayılan olarak “distsDirectory”, JAR’lar ve WAR’lar gibi JAR türevleri için “libsDirectory“dir.
  • archiveVersion Projenin sürümü (version) yoksa varsayılan olarak “$project.version” veya ‘belirtilmemiş (unspecified)’ olur.
  • archiveBaseName Varsayılan olarak $archivesBaseName‘dir.
gradle'ı anlamak (understanding gradle) gradle base plugin build task


Artık ‘:assemble’ ve ‘:build’ görevlerinin mevcut olduğunu görebiliyoruz. “:” ile ayrılmış, alt proje adı ve görev (task) adı ile adreslediğimiz ‘:build’ görevini çalıştırdığımızda pek bir şeyin gerçekleşmediğini görüyoruz.

gradle'ı anlamak (understanding gradle) gradle base plugin build task


gradle'ı anlamak (understanding gradle) gradle base plugin build task


Benim Notum : --console hangi tür konsol çıktısının oluşturulacağını belirtir. Değerler ‘plain’, ‘auto’ (varsayılan), ‘rich’ veya ‘verbose‘dur.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 % gradle :app:build --console=plain
> Task :my-build-logic:java-plugins:checkKotlinGradlePluginConfigurationErrors
> Task :my-build-logic:java-plugins:generateExternalPluginSpecBuilders UP-TO-DATE
> Task :my-build-logic:java-plugins:extractPrecompiledScriptPluginPlugins UP-TO-DATE
> Task :my-build-logic:java-plugins:compilePluginsBlocks UP-TO-DATE
> Task :my-build-logic:java-plugins:generatePrecompiledScriptPluginAccessors UP-TO-DATE
> Task :my-build-logic:java-plugins:generateScriptPluginAdapters UP-TO-DATE
> Task :my-build-logic:java-plugins:compileKotlin UP-TO-DATE
> Task :my-build-logic:java-plugins:compileJava NO-SOURCE
> Task :my-build-logic:java-plugins:pluginDescriptors UP-TO-DATE
> Task :my-build-logic:java-plugins:processResources UP-TO-DATE
> Task :my-build-logic:java-plugins:classes UP-TO-DATE
> Task :my-build-logic:java-plugins:jar UP-TO-DATE
> Task :app:assemble UP-TO-DATE
> Task :app:check UP-TO-DATE
> Task :app:build UP-TO-DATE

Yaşam Döngüsü ve Eyleme Dönüştürülebilir Görevler (Lifecycle and Actionable Tasks)

Gradle’ın iki tür görev (task) arasında ayrım yaptığını bilmek önemlidir: (1) yaşam döngüsü görevleri (lifecycle tasks) ve (2) eyleme dönüştürülebilir görevler (actionable tasks). ‘base’ pluginin eklediği şeyler yalnızca yaşam döngüsü görevleridir (lifecycle tasks).

Yaşam döngüsü görevleri (lifecycle tasks) çağırabileceğiniz (callable) hedefleri tanımlar. Gradle’a projenizi ‘:build’ etmesini söylemek gibi. Ancak ‘base’ plugin, yalnızca bu yaşam döngüsü görevlerini (lifecycle tasks) onlara herhangi bir “actionable” görev bağlamadan ekler.

java-library plugin ve Actionable task’lar


Bu tür “actionable” görevler, Java kaynak kodunu derlemek (compile) veya sınıfları bir “Jar” içinde paketlemek gibi şeyler için görevler sağlayan ‘java-library’ eklentisi gibi eklentiler tarafından eklenir.

gradle'ı anlamak (understanding gradle) gradle actionable tasks, java-library plugin


gradle'ı anlamak (understanding gradle) gradle actionable tasks, java-library plugin


Benim Notum:


“Java Plugin”, görevlerinden bazılarını, Java Eklentisinin otomatik olarak uyguladığı “Base Plugin” tarafından tanımlanan “yaşam döngüsü (lifecycle)” görevlerine ekler ve ayrıca birkaç “yaşam döngüsü (lifecycle)” görevi daha ekler. 3 Benim anladığım üzere burada, tıpkı Java Library Plugin’in Java Plugin’i genişletmesi gibi bir durum var. Yani Java Plugin, Gradle Base Plugin’i genişletiyor.

Artık daha fazla görevin kullanılabilir hale geldiğini ve burada gösterilmeyen “lifecycle” görevlerine daha fazla “actionable” görevin bağlandığını görebiliyoruz.

gradle'ı anlamak (understanding gradle) gradle actionable tasks, java-library plugin


Şimdi ‘:build’ görevini tekrar çağırırsak, ‘:app:compileJava’ görevi de dahil olmak üzere birçok görevin yürütüldüğünü görebiliriz.

gradle'ı anlamak (understanding gradle) gradle actionable tasks, java-library plugin


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
% gradle :app:build --console=plain
Starting a Gradle Daemon (subsequent builds will be faster)
> Task :my-build-logic:java-plugins:checkKotlinGradlePluginConfigurationErrors
> Task :my-build-logic:java-plugins:generateExternalPluginSpecBuilders
> Task :my-build-logic:java-plugins:extractPrecompiledScriptPluginPlugins
> Task :my-build-logic:java-plugins:compilePluginsBlocks
> Task :my-build-logic:java-plugins:generatePrecompiledScriptPluginAccessors
> Task :my-build-logic:java-plugins:generateScriptPluginAdapters
> Task :my-build-logic:java-plugins:pluginDescriptors
> Task :my-build-logic:java-plugins:processResources
> Task :my-build-logic:java-plugins:compileKotlin
> Task :my-build-logic:java-plugins:compileJava NO-SOURCE
> Task :my-build-logic:java-plugins:classes
> Task :my-build-logic:java-plugins:jar
> Task :app:compileJava NO-SOURCE
> Task :app:processResources NO-SOURCE
> Task :app:classes UP-TO-DATE
> Task :app:jar
> Task :app:assemble
> Task :app:compileTestJava NO-SOURCE
> Task :app:processTestResources NO-SOURCE
> Task :app:testClasses UP-TO-DATE
> Task :app:test NO-SOURCE
> Task :app:check UP-TO-DATE
> Task :app:build

Benim Notum : build, check ve assemble dışındaki görevlerin “java-library” plugin ile geldiğini görüyorsunuz. Özetle java-library plugin’in, base plugini genişlettiğini söyleyebiliriz.

Görevler Artımsaldır (Incremental)

Gradle görevlerinin önemli bir yönü artımlılıklarıdır (incrementality). Gradle önceki build’lerden elde edilen sonuçları yeniden kullanabilir (reuse). Dolayısıyla, projemizi zaten build ettiysek ve yalnızca küçük bir şeyi değiştirseydik,, ‘:build’ komutunu tekrar çalıştırmak çok fazla işe neden olmayacaktır.

Benim Notum:


Önceki “build run” sonuçlarını yeniden kullanın

Örneğin, projemizde yalnızca test kodunu değiştirip, üretim (production) koduna dokunmazsak, build’ı çalıştırmak yalnızca test kodunu yeniden derleyecektir, ancak Gradle tarafından “UP-TO-DATE” (yani güncel) olarak işaretlenen production kodunu değiştirmeyecektir.

Şimdi sırasıyla production kodunda sonrasında da test kodunda bir sınıf oluşturup çıktıları aşama aşama inceleyelim.

gradle'ı anlamak (understanding gradle) reuse previous build run


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
% gradle :app:build --console=plain
> Task :my-build-logic:java-plugins:checkKotlinGradlePluginConfigurationErrors
> Task :my-build-logic:java-plugins:generateExternalPluginSpecBuilders UP-TO-DATE
> Task :my-build-logic:java-plugins:extractPrecompiledScriptPluginPlugins UP-TO-DATE
> Task :my-build-logic:java-plugins:compilePluginsBlocks UP-TO-DATE
> Task :my-build-logic:java-plugins:generatePrecompiledScriptPluginAccessors UP-TO-DATE
> Task :my-build-logic:java-plugins:generateScriptPluginAdapters UP-TO-DATE
> Task :my-build-logic:java-plugins:compileKotlin UP-TO-DATE
> Task :my-build-logic:java-plugins:compileJava NO-SOURCE
> Task :my-build-logic:java-plugins:pluginDescriptors UP-TO-DATE
> Task :my-build-logic:java-plugins:processResources UP-TO-DATE
> Task :my-build-logic:java-plugins:classes UP-TO-DATE
> Task :my-build-logic:java-plugins:jar UP-TO-DATE
- > Task :app:compileJava
> Task :app:processResources NO-SOURCE
> Task :app:classes
> Task :app:jar
> Task :app:assemble
- > Task :app:compileTestJava NO-SOURCE
> Task :app:processTestResources NO-SOURCE
> Task :app:testClasses UP-TO-DATE
> Task :app:test NO-SOURCE
> Task :app:check UP-TO-DATE
> Task :app:build

gradle'ı anlamak (understanding gradle) reuse previous build run


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
 % gradle :app:build --console=plain
> Task :my-build-logic:java-plugins:checkKotlinGradlePluginConfigurationErrors
> Task :my-build-logic:java-plugins:generateExternalPluginSpecBuilders UP-TO-DATE
> Task :my-build-logic:java-plugins:extractPrecompiledScriptPluginPlugins UP-TO-DATE
> Task :my-build-logic:java-plugins:compilePluginsBlocks UP-TO-DATE
> Task :my-build-logic:java-plugins:generatePrecompiledScriptPluginAccessors UP-TO-DATE
> Task :my-build-logic:java-plugins:generateScriptPluginAdapters UP-TO-DATE
> Task :my-build-logic:java-plugins:compileKotlin UP-TO-DATE
> Task :my-build-logic:java-plugins:compileJava NO-SOURCE
> Task :my-build-logic:java-plugins:pluginDescriptors UP-TO-DATE
> Task :my-build-logic:java-plugins:processResources UP-TO-DATE
> Task :my-build-logic:java-plugins:classes UP-TO-DATE
> Task :my-build-logic:java-plugins:jar UP-TO-DATE
- > Task :app:compileJava UP-TO-DATE
> Task :app:processResources NO-SOURCE
> Task :app:classes UP-TO-DATE
> Task :app:jar UP-TO-DATE
> Task :app:assemble UP-TO-DATE
- > Task :app:compileTestJava UP-TO-DATE
> Task :app:processTestResources NO-SOURCE
> Task :app:testClasses UP-TO-DATE
> Task :app:test UP-TO-DATE
> Task :app:check UP-TO-DATE
> Task :app:build UP-TO-DATE

Şekilde görüldüğü gibi sadece src/test/java/Test.java sınıfında bir değişiklik yapıyoruz.

gradle'ı anlamak (understanding gradle) reuse previous build run


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
% gradle :app:build --console=plain
> Task :my-build-logic:java-plugins:checkKotlinGradlePluginConfigurationErrors
> Task :my-build-logic:java-plugins:generateExternalPluginSpecBuilders UP-TO-DATE
> Task :my-build-logic:java-plugins:extractPrecompiledScriptPluginPlugins UP-TO-DATE
> Task :my-build-logic:java-plugins:compilePluginsBlocks UP-TO-DATE
> Task :my-build-logic:java-plugins:generatePrecompiledScriptPluginAccessors UP-TO-DATE
> Task :my-build-logic:java-plugins:generateScriptPluginAdapters UP-TO-DATE
> Task :my-build-logic:java-plugins:compileKotlin UP-TO-DATE
> Task :my-build-logic:java-plugins:compileJava NO-SOURCE
> Task :my-build-logic:java-plugins:pluginDescriptors UP-TO-DATE
> Task :my-build-logic:java-plugins:processResources UP-TO-DATE
> Task :my-build-logic:java-plugins:classes UP-TO-DATE
> Task :my-build-logic:java-plugins:jar UP-TO-DATE
- > Task :app:compileJava UP-TO-DATE
> Task :app:processResources NO-SOURCE
> Task :app:classes UP-TO-DATE
> Task :app:jar UP-TO-DATE
> Task :app:assemble UP-TO-DATE
- > Task :app:compileTestJava
> Task :app:processTestResources NO-SOURCE
> Task :app:testClasses
> Task :app:test
> Task :app:check
> Task :app:build

Değişiklik yapmadığım src/main/java/Test.java sınıfını derlemek için kullanılan task, compileJava UP-TO-DATE olarak etiketli kalırken, src/test/java/Test.java sınıfını derlemek için kullanılan compileTestJava görevi etiketsiz kalmaktadır. Bu, ilgili görevin yeniden çalıştırıldığının bir işaretidir.

Build Cache Sonuçları Yeniden Kullanma

Gradle ayrıca geçmişteki sonuçları da yeniden kullanabilir. Bunun için “Build Cache”‘i etkinleştirmeniz gerekir. Bunu “--build-cache” komut satırı parametresi aracılığıyla veya “gradle.properties” dosyasında bir özellik (property) ayarlayarak yapabilirsiniz. Bu, build’lerinizi büyük ölçüde hızlandırabilir.

gradle'ı anlamak (understanding gradle) gradle reuse Build Cache


gradle'ı anlamak (understanding gradle) gradle reuse Build Cache


Örneğin, branch’ler arasında düzenli olarak geçiş yapıyorsanız, “build cache” uzak bir sunucuda (remote server) da bulunabilir ve birden fazla makine arasında da paylaşılabilir. Bu kurulumla CI sunucusu “build cache”‘i doldurabilir ve birden fazla geliştirici sonuçları yeniden kullanabilir.

Görevler arasında bağımlılıklar (dependencies) vardır

Gradle’ın tüm görevler (tasks) arasındaki bağımlılıkları (dependencies) bildiğini anlamak önemlidir. Bu sayede hangi görevi hedef alırsanız alın, diğer hangi görevlerin yürütülmesi gerektiğini bilirsiniz.

app” alt projemize bir bağımlılık ekleyelim.

gradle'ı anlamak (understanding gradle) dependencies between tasks


“app” projesi artık diğer iki alt projemize bağlıdır: doğrudan “business-logic” projesine ve dolaylı olarak “data-model” projesine bağımlıdır. Şimdi ‘:build’i tekrar çalıştırırsak bu projelerin Java kodlarının nasıl derlendiğini de görmüş oluruz.

gradle'ı anlamak (understanding gradle) dependencies between tasks


Benim Notum:


Task dependencies

Diğer görevlere bağlı olan görevleri bildirebilirsiniz:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//build.gradle.kts

tasks.register("hello") {
  doLast {
    println("Hello world!")
  }
}
tasks.register("intro") {
  dependsOn("hello")
  doLast {
    println("I'm Gradle")
  }
}

1
2
3
$ gradle -q intro
Hello world!
I'm Gradle

taskX‘in taskY‘ye bağımlılığı, taskY tanımlanmadan önce bildirilebilir:

1
2
3
4
5
6
7
8
9
10
11
12
13
//build.gradle.kts

tasks.register("taskX") {
  dependsOn("taskY")
  doLast {
    println("taskX")
  }
}
tasks.register("taskY") {
  doLast {
    println("taskY")
  }
}
1
2
3
$ gradle -q taskX
taskY
taskX

Önceki örnekteki hello görevi bir bağımlılık içerecek şekilde güncellendi:

1
2
3
4
5
6
7
8
9
10
//build.gradle.kts

tasks.register("hello") {
  group = "Custom"
  description = "A lovely greeting task."
  doLast {
    println("Hello world!")
  }
  dependsOn(tasks.assemble)
}

hello görevi artık assemble görevine bağlıdır; bu, Gradle’ın hello görevini yürütmeden önce assemble görevini yürütmesi gerektiği anlamına gelir:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ ./gradlew :app:hello

> Task :app:compileJava UP-TO-DATE
> Task :app:processResources NO-SOURCE
> Task :app:classes UP-TO-DATE
> Task :app:jar UP-TO-DATE
> Task :app:startScripts UP-TO-DATE
> Task :app:distTar UP-TO-DATE
> Task :app:distZip UP-TO-DATE
> Task :app:assemble UP-TO-DATE

> Task :app:hello
Hello world!

Referanslar:

Daha Fazla Okuma:

Syncing and reloading The Gradle Tool Window Use “Load Gradle Changes” The Right Way in IntelliJ IDEA