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

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

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

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

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

ציר הזמן

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

תקופות ביטוח מקובלות

Kotlin DSL: מתייחס בעיקר ל-Android Gradle plugin Kotlin DSL או, מדי פעם, ל-underlying Gradle Kotlin DSL.

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

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

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

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

המרת התחביר

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

הוספת סוגריים לקריאות של שיטות

ב-Groovy אפשר להשמיט סוגריים בקריאות ל-method, אבל ב-Kotlin הם נדרשים. כדי להעביר את ההגדרה, מוסיפים סוגריים לקריאות לשיטות מהסוגים האלה. הקוד הבא מראה איך להגדיר הגדרה ב-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() on 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 של debug ו-release זמינים באופן מרומז. צריך ליצור ידנית את כל שאר סוגי הבנייה בהתאמה אישית.

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

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

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

buildTypes {
 debug {
   ...
 }

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

העברה מ-buildscript לבלוק plugins

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

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

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

בלוק buildscript {} מוסיף את הפלאגינים לנתיב המחלקה של ה-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

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

אפשר להפנות לפלאגינים של 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 ברמת המודול. כאן צריך לציין רק את המזהה של הפלאגין, כי הגרסה עוברת בירושה מפרויקט הבסיס.

  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 {}, אפשר לעיין במאמר הוספת פלאגינים במסמכי התיעוד של Gradle.

שונות

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

בעיות מוכרות

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

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

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

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

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