העברת תצורת ה-build מ-Groovy ל-Kotlin

בגרסה 4.0 של הפלאגין של Android Gradle נוספה תמיכה בשימוש ב-Kotlin בהגדרות ה-build של Gradle, כתחליף ל-Groovy, שפת התכנות שבה נהוג להשתמש בקובצי התצורה של Gradle.

מומלץ להשתמש ב-Kotlin במקום ב-Groovy לכתיבה של סקריפטים של Gradle, כי קל יותר לקרוא ב-Kotlin ויש בה בדיקה טובה יותר בזמן הידור ותמיכה טובה יותר ב-IDE.

אמנם בשלב הזה, Kotlin מציעה שילוב טוב יותר בכלי העריכה של Android Studio בהשוואה ל-Groovy, אבל גרסאות build שמבוססות על Kotlin נוטים להיות איטיות יותר מגרסאות build שמבוססות על Groovy. לכן, כדאי להביא בחשבון את ביצועי ה-build כשמחליטים אם לעבור ל-Kotlin.

בדף הזה נספק מידע בסיסי על המרת קובצי ה-build של אפליקציית Android מ-Groovy ל-Kotlin. למדריך מקיף יותר להעברה, עיינו במסמכי התיעוד הרשמיים של Gradle.

ציר הזמן

החל מגרסה Android Studio Giraffe, פרויקטים חדשים משתמשים ב-Kotlin DSL (build.gradle.kts) כברירת מחדל להגדרת build. כך תוכלו ליהנות מחוויית עריכה טובה יותר מאשר ב-Groovy DSL‏ (build.gradle), עם הדגשת תחביר, השלמת קוד ואפשרות ניווט להצהרות. למידע נוסף, קראו את המאמר Gradle Kotlin DSL Primer.

מונחים נפוצים

Kotlin DSL: מתייחס בעיקר ל-Kotlin DSL של הפלאגין Android Gradle, או לפעמים ל-Kotlin DSL הבסיסי של Gradle.

במדריך הזה להעברת נתונים, אנחנו משתמשים במונחים 'Kotlin' ו-'Kotlin DSL' לסירוגין. באופן דומה, אפשר להשתמש ב-Groovy וב-Groovy DSL לאותה מטרה.

מתן שמות לקובצי סקריפט

שמות הסיומת של קובצי הסקריפט מבוססים על השפה שבה נכתב קובץ ה-build:

  • קובצי build של Gradle שנכתבו ב-Groovy משתמשים בסיומת .gradle של שם הקובץ.
  • קובצי build של Gradle שנכתבו ב-Kotlin משתמשים בסיומת .gradle.kts בשם הקובץ.

המרת התחביר

יש כמה הבדלים כלליים בתחביר בין Groovy ל-Kotlin, ולכן צריך להחיל את השינויים האלה בכל סקריפט ה-build.

הוספת סוגריים לקריאות ל-method

ב-Groovy אפשר להשמיט סוגריים בקריאות ל-method, בעוד שב-Kotlin צריך להשתמש בהם. כדי להעביר את ההגדרות, צריך להוסיף סוגריים לקריאות האלה ל-method. הקוד הזה מראה איך להגדיר הגדרה ב-Groovy:

compileSdkVersion 30

זהו אותו קוד שנכתב ב-Kotlin:

compileSdkVersion(30)

הוספת = לשיחות של מטלות

ב-Groovy DSL אפשר להשמיט את אופרטור ההקצאה = כשמקצים מאפיינים, בעוד שב-Kotlin הוא נדרש. הקוד הזה מראה איך מקצים מאפיינים ב-Groovy:

java {
    sourceCompatibility JavaVersion.VERSION_17
    targetCompatibility JavaVersion.VERSION_17
}

הקוד הזה מראה איך להקצות מאפיינים ב-Kotlin:

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

המרת מחרוזות

אלה ההבדלים בין מחרוזות ב-Groovy לבין מחרוזות ב-Kotlin:

  • מירכאות כפולות למחרוזות: ב-Groovy אפשר להגדיר מחרוזות באמצעות גרשיים, אבל ב-Kotlin נדרש שימוש במירכאות כפולות.
  • הוספת מחרוזות לביטויים עם נקודות: ב-Groovy אפשר להשתמש רק בתחילית $ להוספת מחרוזות לביטויים עם נקודות, אבל ב-Kotlin צריך לעטוף את הביטויים עם נקודות בסוגריים מסולסלים. לדוגמה, ב-Groovy אפשר להשתמש ב-$project.rootDir, כפי שמתואר בקטע הקוד הבא:

        myRootDirectory = "$project.rootDir/tools/proguard-rules-debug.pro"
        

    עם זאת, ב-Kotlin, הקוד הקודם קורא ל-toString() ב-project, ולא ב-project.rootDir. כדי לקבל את הערך של ספריית הבסיס, צריך לעטוף את הביטוי ${project.rootDir} בסוגריים מסולסלים:

        myRootDirectory = "${project.rootDir}/tools/proguard-rules-debug.pro"
        

    מידע נוסף זמין במאמר תבניות מחרוזות במסמכי התיעוד של Kotlin.

שינוי השם של סיומות קבצים

מוסיפים את .kts לכל קובץ build בזמן העברת התוכן שלו. לדוגמה, בוחרים קובץ build, כמו הקובץ settings.gradle. משנים את שם הקובץ ל-settings.gradle.kts וממירים את תוכן הקובץ ל-Kotlin. חשוב לוודא שהפרויקט עדיין עובר הידור אחרי ההעברה של כל קובץ build.

מומלץ להעביר קודם את הקבצים הקטנים ביותר, לצבור ניסיון ואז להמשיך. אפשר לשלב בפרויקט קבצי build של Kotlin ו-Groovy, לכן כדאי להקדיש זמן כדי לבצע את המעבר בזהירות.

מחליפים את def ב-val או ב-var

מחליפים את def ב-val או ב-var, כך מגדירים משתנים ב-Kotlin. זוהי הצהרת משתנה ב-Groovy:

def building64Bit = false

זהו אותו קוד שנכתב ב-Kotlin:

val building64Bit = false

הוספת הקידומת is לנכסים בוליאניים

ב-Groovy נעשה שימוש בלוגיקה של ניכוי מאפיינים על סמך שמות המאפיינים. לנכס בוליאני foo, השיטות המוסקות יכולות להיות getFoo,‏ setFoo או isFoo. לכן, אחרי ההמרה ל-Kotlin, צריך לשנות את שמות המאפיינים לשיטות המופשטות שלא נתמכות ב-Kotlin. לדוגמה, כדי להשתמש באלמנטים בוליאנים של buildTypes DSL, צריך להוסיף להם את הקידומת is. הקוד הזה מראה איך מגדירים מאפיינים בוליאניים ב-Groovy:

android {
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            ...
        }
        debug {
            debuggable true
            ...
        }
    ...

זהו אותו קוד ב-Kotlin. שימו לב שהתחילית של המאפיינים היא is.

android {
    buildTypes {
        getByName("release") {
            isMinifyEnabled = true
            isShrinkResources = true
            ...
        }
        getByName("debug") {
            isDebuggable = true
            ...
        }
    ...

המרת רשימות ומפות

רשימות ומפות ב-Groovy וב-Kotlin מוגדרות באמצעות תחביר שונה. ב-Groovy נעשה שימוש ב-[], בעוד שב-Kotlin קוראים לשיטות ליצירת אוספים באופן מפורש באמצעות listOf או mapOf. חשוב להחליף את [] ב-listOf או ב-mapOf במהלך ההעברה.

כך מגדירים רשימה ב-Groovy לעומת Kotlin:

jvmOptions += ["-Xms4000m", "-Xmx4000m", "-XX:+HeapDumpOnOutOfMemoryError</code>"]

זהו אותו קוד שנכתב ב-Kotlin:

jvmOptions += listOf("-Xms4000m", "-Xmx4000m", "-XX:+HeapDumpOnOutOfMemoryError")

כך מגדירים מפה ב-Groovy לעומת Kotlin:

def myMap = [key1: 'value1', key2: 'value2']

זהו אותו קוד שנכתב ב-Kotlin:

val myMap = mapOf("key1" to "value1", "key2" to "value2")

הגדרת סוגי build

ב-Kotlin DSL, רק סוגי ה-build של ניפוי באגים ושל גרסה זמינים באופן משתמע. צריך ליצור באופן ידני את כל סוגי ה-build המותאמים אישית האחרים.

ב-Groovy אפשר להשתמש בסוגי build מסוימים, כמו debug,‏ release ועוד, בלי ליצור אותם קודם. קטע הקוד הבא מציג הגדרה עם סוגי ה-build debug,‏ release ו-benchmark ב-Groovy.

buildTypes {
 debug {
   ...
 }
 release {
   ...
 }
 benchmark {
   ...
 }
}

כדי ליצור את ההגדרה המקבילה ב-Kotlin, צריך ליצור את סוג ה-build benchmark באופן מפורש.

buildTypes {
 debug {
   ...
 }

 release {
   ...
 }
 register("benchmark") {
    ...
 }
}

מעבר מ-buildscript לבלוק של פלאגינים

אם ב-build שלכם נעשה שימוש בבלוק buildscript {} כדי להוסיף יישומי פלאגין לפרויקט, עליכם לבצע רפאקציה (refactor) כדי להשתמש במקום זאת בבלוק plugins {}. בעזרת הבלוק plugins {} קל יותר להחיל פלאגינים, והוא פועל היטב עם קטלוגים של גרסאות.

בנוסף, כשמשתמשים בבלוק plugins {} בקובצי ה-build, Android Studio מזהה את ההקשר גם כשה-build נכשל. ההקשר הזה עוזר לבצע תיקונים בקובצי ה-DSL של Kotlin, כי הוא מאפשר לסביבת הפיתוח המשולבת של Studio לבצע השלמה אוטומטית של קוד ולספק הצעות מועילות אחרות.

איך מוצאים את מזהי הפלאגינים

בעוד שהבלוק buildscript {} מוסיף את הפלאגינים לנתיב ה-classpath של ה-build באמצעות הקואורדינטות של Maven של הפלאגין, למשל com.android.tools.build:gradle:7.4.0, בבלוק plugins {} נעשה שימוש במזהי הפלאגין במקום זאת.

ברוב הפלאגינים, מזהה הפלאגין הוא המחרוזת שמשמשת כשמחילים אותם באמצעות apply plugin. לדוגמה, מזהי הפלאגינים הבאים הם חלק מAndroid Gradle Plugin:

  • com.android.application
  • com.android.library
  • com.android.lint
  • com.android.test

רשימת הפלאגינים המלאה מופיעה במאגר Maven של Google.

אפשר להפנות לפלאגינים של Kotlin באמצעות כמה מזהי פלאגין. מומלץ להשתמש במזהה הפלאגין במרחב השמות, ולבצע רפאקציה מקיצור דרך למזהה הפלאגין במרחב השמות לפי הטבלה הבאה:

מזהים מקוצרים של פלאגינים מזהי פלאגין במרחב שמות
kotlin org.jetbrains.kotlin.jvm
kotlin-android org.jetbrains.kotlin.android
kotlin-kapt org.jetbrains.kotlin.kapt
kotlin-parcelize org.jetbrains.kotlin.plugin.parcelize

אפשר גם לחפש פלאגינים ב-Gradle Plugin Portal, ב-Maven Central Repository וב-Google Maven repository. במאמר פיתוח פלאגינים מותאמים אישית של Gradle מוסבר בהרחבה איך פועלים מזהי הפלאגינים.

ביצוע הרפורמה

אחרי שמוצאים את המזהים של הפלאגינים שבהם אתם משתמשים, מבצעים את השלבים הבאים:

  1. אם עדיין יש לכם מאגרים של יישומי פלאגין שהוגדרו בבלוק buildscript {}, תוכלו להעביר אותם לקובץ settings.gradle במקום זאת.

  2. מוסיפים את התוספים לבלוק plugins {} בקובץ build.gradle ברמה העליונה. כאן צריך לציין את המזהה ואת הגרסה של הפלאגין. אם אין צורך להחיל את הפלאגין על פרויקט הבסיס, משתמשים ב-apply false.

  3. מסירים את הרשומות של classpath מקובץ build.gradle.kts ברמה העליונה.

  4. כדי להחיל את הפלאגינים, מוסיפים אותם לבלוק plugins {} בקובץ build.gradle ברמת המודול. צריך לציין כאן רק את המזהה של הפלאגין, כי הגרסה עוברת בירושה מהפרויקט ברמה הבסיסית (root).

  5. מסירים את הקריאה apply plugin לתוסף מקובץ build.gradle ברמת המודול.

לדוגמה, בהגדרה הזו נעשה שימוש בבלוק buildscript {}:

// Top-level build.gradle file
buildscript {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
    dependencies {
        classpath("com.android.tools.build:gradle:7.4.0")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0")
        ...
    }
}

// Module-level build.gradle file
apply(plugin: "com.android.application")
apply(plugin: "kotlin-android")

זוהי הגדרה מקבילה באמצעות הבלוק plugins {}:

// Top-level build.gradle file
plugins {
   id 'com.android.application' version '7.4.0' apply false
   id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
   ...
}

// Module-level build.gradle file
plugins {
   id 'com.android.application'
   id 'org.jetbrains.kotlin.android'
   ...
}

// settings.gradle
pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}

המרת הבלוק של יישומי הפלאגין

החלת פלאגינים מהבלוק plugins {} דומה ב-Groovy וב-Kotlin. הקוד הבא מראה איך מחילים יישומי פלאגין ב-Groovy כשמשתמשים בקטלוגים של גרסאות:

// Top-level build.gradle file
plugins {
   alias libs.plugins.android.application apply false
   ...
}

// Module-level build.gradle file
plugins {
   alias libs.plugins.android.application
   ...
}

הקוד הבא מראה איך לעשות את אותו הדבר ב-Kotlin:

// Top-level build.gradle.kts file
plugins {
   alias(libs.plugins.android.application) apply false
   ...
}

// Module-level build.gradle.kts file
plugins {
   alias(libs.plugins.android.application)
   ...
}

הקוד הבא מראה איך מחילים פלאגינים ב-Groovy כשלא משתמשים בקטלוגים של גרסאות:

// Top-level build.gradle file
plugins {
   id 'com.android.application' version '7.3.0' apply false
   ...
}

// Module-level build.gradle file
plugins {
   id 'com.android.application'
   ...
}

הקוד הבא מראה איך לעשות את אותו הדבר ב-Kotlin:

// Top-level build.gradle.kts file
plugins {
   id("com.android.application") version "7.3.0" apply false
   ...
}

// Module-level build.gradle.kts file
plugins {
   id("com.android.application")
   ...
}

פרטים נוספים על הבלוק plugins {} זמינים במאמר Applying plugins בתיעוד של Gradle.

שונות

בדפי המסמכים הבאים תוכלו למצוא דוגמאות לקוד Kotlin לפונקציונליות אחרת:

בעיות מוכרות

נכון לעכשיו, בעיה ידועה היא שעשויה להיות מהירות build איטית יותר ב-Kotlin מאשר ב-Groovy.

איך מדווחים על בעיות

הוראות לשליחת המידע שנחוץ לנו כדי לסווג את הבעיה מפורטות במאמר פרטים לגבי כלי build ובאגים ב-Gradle. לאחר מכן, תוכלו לדווח על הבאג באמצעות כלי המעקב הציבורי אחר בעיות של Google.

משאבים נוספים

דוגמה עובדת לקובצי build של Gradle שנכתבו ב-Kotlin מופיעה באפליקציית הדוגמה Now In Android ב-GitHub.