İlk KMP Projesini Yapılandırın: Kotlin Multiplatform ile Android, iOS ve Masaüstü
Sıfırdan bir Kotlin Multiplatform projesi oluşturmak, tüm KMP yolculuğunun en teknik adımlarından biridir.
Flutter'ın aksine flutter create İhtiyacınız olan her şeyi üretir veya React Native'de
Expo karmaşıklığı ele alır, KMP, Gradle'ın, kaynak seti yapısının sağlam bir şekilde anlaşılmasını gerektirir.
ve paylaşılan mantığın ilk satırını yazmadan önce beklenen/gerçek mekanizma.
Bu kılavuz sizi boş projenizi oluşturmaktan kodlu çalışan bir uygulamaya götürür Android ve iOS arasında paylaşılan, her yapılandırma adımını ayrıntılı açıklamalarla gösteren. Sonunda doğru yapıya sahip, Gradle sürüm kataloğu yapılandırılmış ve ilk olan bir projeye sahip olacaksınız. beklenen/gerçek işlevler çalışıyor.
Önkoşullar
- KMP eklentisinin yüklü olduğu Android Studio Hedgehog (2023.1.1) veya üzeri
- Xcode 15+ (iOS uygulamasını oluşturmak için — yalnızca macOS'ta)
- JDK 17+ JAVA_HOME olarak yapılandırılmış
- Kotlin ve Gradle hakkında temel bilgiler
Adım 1: KMP Sihirbazı ile Projeyi Oluşturun
Başlamanın en hızlı yolu, Kotlin Çoklu Platform Sihirbazı mevcut
adreste kmp.jetbrains.com veya doğrudan Android Studio'dan
Dosya → Yeni → Yeni Proje → Kotlin Multiplatform App.
# Alternativa da riga di comando con il KMP Wizard CLI (2026)
# Installa il plugin KMP di IntelliJ/Android Studio dal marketplace
# oppure usa il sito web:
# 1. Vai su https://kmp.jetbrains.com
# 2. Configura: nome progetto, package, target (Android, iOS, Desktop)
# 3. Scarica il progetto e aprilo in Android Studio
# Struttura generata dal wizard:
my-kmp-app/
├── composeApp/ # (se scegli Compose Multiplatform)
│ └── build.gradle.kts
├── shared/ # Il modulo condiviso principale
│ ├── src/
│ │ ├── commonMain/
│ │ ├── androidMain/
│ │ └── iosMain/
│ └── build.gradle.kts
├── androidApp/ # App Android standalone
│ └── build.gradle.kts
├── iosApp/ # App iOS standalone (Swift)
│ └── iosApp.xcodeproj
├── gradle/
│ └── libs.versions.toml # Version catalog
├── build.gradle.kts # Root build script
└── settings.gradle.kts
Adım 2: Sürüm Kataloğu (libs.versions.toml)
Il Gradle Sürüm Kataloğu tümünün sürüm yönetimini merkezileştirir tek bir TOML dosyasındaki proje bağımlılıkları. JetBrains tarafından önerilen en iyi uygulamadır KMP projeleri için:
# gradle/libs.versions.toml
[versions]
kotlin = "2.0.20"
kotlinx-coroutines = "1.9.0"
kotlinx-serialization = "1.7.3"
ktor = "2.3.12"
sqldelight = "2.0.2"
koin = "3.5.6"
agp = "8.5.2"
compose-multiplatform = "1.7.0"
kotlinx-datetime = "0.6.1"
[libraries]
# Kotlin
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
# Coroutines
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
# Serialization
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
# Ktor
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" }
ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor" }
ktor-client-content-negotiation = { module = "io.ktor:ktor-client-content-negotiation", version.ref = "ktor" }
ktor-serialization-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
# SQLDelight
sqldelight-runtime = { module = "app.cash.sqldelight:runtime", version.ref = "sqldelight" }
sqldelight-android-driver = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" }
sqldelight-native-driver = { module = "app.cash.sqldelight:native-driver", version.ref = "sqldelight" }
sqldelight-coroutines = { module = "app.cash.sqldelight:coroutines-extensions", version.ref = "sqldelight" }
# Koin DI
koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" }
koin-android = { module = "io.insert-koin:koin-android", version.ref = "koin" }
# DateTime
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
android-library = { id = "com.android.library", version.ref = "agp" }
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
compose-multiplatform = { id = "org.jetbrains.compose", version.ref = "compose-multiplatform" }
sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" }
Adım 3: Paylaşılan Modül Oluşturma Komut Dosyası
Il build.gradle.kts Paylaşılan modülün en önemli yapılandırma dosyasıdır
projenin. Her birinin derleme hedeflerini, kaynak kümelerini ve bağımlılıklarını tanımlar:
// shared/build.gradle.kts
plugins {
alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.sqldelight)
}
kotlin {
// Target Android
androidTarget {
compilations.all {
kotlinOptions {
jvmTarget = "17"
}
}
}
// Target iOS (arm64 per device, x64 per simulator Intel, simulatorArm64 per M1/M2)
listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach { iosTarget ->
iosTarget.binaries.framework {
baseName = "Shared"
isStatic = true
}
}
// Target Desktop JVM (opzionale)
jvm("desktop")
sourceSets {
// Codice comune a tutte le piattaforme
commonMain.dependencies {
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.serialization.json)
implementation(libs.ktor.client.core)
implementation(libs.ktor.client.content.negotiation)
implementation(libs.ktor.serialization.json)
implementation(libs.sqldelight.runtime)
implementation(libs.sqldelight.coroutines)
implementation(libs.koin.core)
implementation(libs.kotlinx.datetime)
}
// Test comuni
commonTest.dependencies {
implementation(libs.kotlin.test)
}
// Android-specific
androidMain.dependencies {
implementation(libs.ktor.client.okhttp)
implementation(libs.sqldelight.android.driver)
implementation(libs.kotlinx.coroutines.android)
}
// iOS-specific
val iosMain by getting {
// Su iOS non puoi usare "iosMain" direttamente se hai piu target iOS
// Usa una convenzione condivisa per i tre target iOS
}
val iosX64Main by getting
val iosArm64Main by getting
val iosSimulatorArm64Main by getting
// Source set condiviso per tutti i target iOS
create("iosMain") {
dependsOn(commonMain.get())
iosX64Main.dependsOn(this)
iosArm64Main.dependsOn(this)
iosSimulatorArm64Main.dependsOn(this)
dependencies {
implementation(libs.ktor.client.darwin)
implementation(libs.sqldelight.native.driver)
}
}
}
}
android {
namespace = "com.example.mykmpapp.shared"
compileSdk = 35
defaultConfig {
minSdk = 26
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
}
sqldelight {
databases {
create("AppDatabase") {
packageName.set("com.example.mykmpapp.db")
}
}
}
Adım 4: Kaynak Kümelerini Anlama
I kaynak seti bunlar KMP'nin temel yapısıdır. Her kaynak seti bir tanedir
bağımlılıklarıyla birlikte Kotlin kodunun dizinleri ve kaynak kümeleri başkalarına bağlı olabilir
hiyerarşi aracılığıyla dependsOn:
// Gerarchia dei source set tipica
commonMain
├── androidMain (usa librerie Android: OkHttp, Android SQLite)
├── iosMain (usa librerie Darwin: URLSession, iOS SQLite)
│ ├── iosX64Main
│ ├── iosArm64Main
│ └── iosSimulatorArm64Main
└── desktopMain (usa librerie JVM: OkHttp, SQLite JDBC)
// Tutti i source set "eredita" le dipendenze di commonMain
// androidMain puo usare tutto di commonMain + dipendenze Android-specific
Proje dosya sisteminde dizin yapısı kaynak kümelerini yansıtır:
shared/src/
├── commonMain/
│ └── kotlin/
│ └── com/example/mykmpapp/
│ ├── data/
│ ├── domain/
│ └── Platform.kt # expect declaration
├── androidMain/
│ └── kotlin/
│ └── com/example/mykmpapp/
│ └── Platform.android.kt # actual per Android
└── iosMain/
└── kotlin/
└── com/example/mykmpapp/
└── Platform.ios.kt # actual per iOS
Adım 5: İlk beklenen/gerçek İşlevler
Mekanizma beklenen/gerçek ve KMP'nin platforma özgü farklılıkları nasıl ele aldığı.
expect API'yi ortak kodda beyan edin, actual her biri için uygular
platformu. Klasik bir örnekle başlayalım: Mevcut platform hakkında bilgi almak:
// commonMain/kotlin/com/example/mykmpapp/Platform.kt
expect class PlatformInfo() {
val name: String
val version: String
val isDebug: Boolean
}
// Funzione che usa l'implementazione platform-specific
fun greeting(): String = "Running on ${PlatformInfo().name} ${PlatformInfo().version}"
// androidMain/kotlin/com/example/mykmpapp/Platform.android.kt
import android.os.Build
actual class PlatformInfo {
actual val name: String = "Android ${Build.VERSION.RELEASE}"
actual val version: String = Build.VERSION.SDK_INT.toString()
actual val isDebug: Boolean = BuildConfig.DEBUG
}
// iosMain/kotlin/com/example/mykmpapp/Platform.ios.kt
import platform.UIKit.UIDevice
actual class PlatformInfo {
actual val name: String = UIDevice.currentDevice.systemName()
actual val version: String = UIDevice.currentDevice.systemVersion
actual val isDebug: Boolean = Platform.isDebugBinary
}
Daha pratik ikinci bir örnek: UUID oluşturmak (platform başına farklı API'ler kullanan):
// commonMain: dichiarazione expect
expect fun generateUUID(): String
// androidMain: implementazione con java.util.UUID
actual fun generateUUID(): String = java.util.UUID.randomUUID().toString()
// iosMain: implementazione con NSUUID di iOS
import platform.Foundation.NSUUID
actual fun generateUUID(): String = NSUUID().UUIDString()
6. Adım: Android Uygulamasını Yapılandırın
Android uygulaması, paylaşılan modüle bağlı standart bir Gradle modülüdür. Yapılandırma ve basit:
// androidApp/build.gradle.kts
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
}
android {
namespace = "com.example.mykmpapp.android"
compileSdk = 35
defaultConfig {
applicationId = "com.example.mykmpapp"
minSdk = 26
targetSdk = 35
versionCode = 1
versionName = "1.0"
}
buildFeatures {
compose = true
}
}
dependencies {
// Dipende dal modulo shared
implementation(projects.shared)
// UI Android (Compose o View-based)
implementation(platform("androidx.compose:compose-bom:2026.01.00"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.material3:material3")
implementation("androidx.activity:activity-compose:1.9.3")
}
7. Adım: iOS Uygulamasını Yapılandırın
iOS entegrasyonu, Xcode'u derlenmiş KMP çerçevesini içerecek şekilde yapılandırmanızı gerektirir.
Paylaşılan modül bir iOS çerçevesinde derlenmiştir (Shared.xcframework) bu
Xcode uygulamasına bağlı:
# Script di build iOS da aggiungere come Xcode Build Phase:
# "Run Script" - da aggiungere in Build Phases di Xcode
cd "$SRCROOT/.."
# Compila il framework KMP per il target iOS corrente
if [ "$PLATFORM_NAME" = "iphonesimulator" ]; then
if [ "$ARCHS" = "arm64" ]; then
TARGET="iosSimulatorArm64"
else
TARGET="iosX64"
fi
else
TARGET="iosArm64"
fi
./gradlew "shared:link${TARGET}DebugFrameworkIos${TARGET^}" \
-Pkotlin.native.useEmbeddableCompilerJar=true
# Il framework viene copiato automaticamente da Gradle
iOS uygulamasının Swift dosyasında çerçeve, normal bir Swift çerçevesi gibi içe aktarılır:
// iosApp/ContentView.swift
import SwiftUI
import Shared // Il framework KMP compilato
struct ContentView: View {
@State private var greeting = ""
var body: some View {
VStack {
Text(greeting)
.padding()
Button("Refresh") {
greeting = Greeting().greeting()
}
}
.onAppear {
// Chiama il codice Kotlin dal framework condiviso
greeting = PlatformInfoKt.greeting()
}
}
}
Adım 8: Paylaşılan Modülün İlk Testi
Paylaşılan modülde bir birim testi yazıp çalıştırarak her şeyin çalıştığını doğrulayın.
Ortak testlerAna kullanımlar kotlin.test tüm platformlarda çalışır:
// commonTest/kotlin/com/example/mykmpapp/PlatformTest.kt
import kotlin.test.Test
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
class PlatformTest {
@Test
fun testPlatformInfoNotNull() {
val info = PlatformInfo()
assertNotNull(info.name)
assertNotNull(info.version)
}
@Test
fun testGreetingContainsPlatform() {
val greet = greeting()
assertTrue(greet.contains("Running on"), "Greeting dovrebbe contenere 'Running on'")
}
@Test
fun testUUIDFormat() {
val uuid = generateUUID()
// UUID formato: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
assertTrue(uuid.length == 36, "UUID dovrebbe avere 36 caratteri")
assertTrue(uuid.count { it == '-' } == 4, "UUID dovrebbe avere 4 trattini")
}
}
# Esegui i test sul target JVM (piu veloce, per CI)
./gradlew shared:jvmTest
# Esegui i test su Android (emulatore o device)
./gradlew shared:connectedAndroidTest
# Esegui i test iOS (solo su macOS)
./gradlew shared:iosSimulatorArm64Test
Yaygın Sorunlar ve Çözümler
- "Kotlin/Yerel araç zinciri bulunamadı" hatası: Sahip olduğunuzdan emin olun JAVA_HOME olarak yapılandırılmış JDK 17+ ve Gradle'ın araç zincirini indirdiği Kotlin/Native (bu nedenle ilk derleme daha yavaştır).
-
"gerçek bildirim bulunamadı" hatası: Kullanıyorsun
expectkarşılık gelen bir tane sağlamadanactualiçin tüm yapılandırılmış hedefler. Gerçek sınıfın/fonksiyonun mevcut olup olmadığını kontrol edin yapılandırılan tüm kaynak kümelerindekotlin { }. - Güncel olmayan iOS çerçevesi: Kotlin kodunda yapılan değişikliklerden sonra, Xcode yapısını temizleyin (Cmd+Shift+K) ve yeniden derleyin. Çerçeve şöyle olmalı Xcode görebilmeden önce Gradle ile yeniden derlendi.
- Kütüphane uyumluluğu: Tüm Java kitaplıkları çalışmıyor iOS. README'de her zaman "KMP" veya "Kotlin Multiplatform" etiketi bulunan kütüphaneleri kullanın.
Final Projesinin Yapısı
Bu konfigürasyonun sonunda projeniz şu operasyonel yapıya sahip olur:
my-kmp-app/
├── gradle/
│ └── libs.versions.toml # Version catalog centralizzato
├── shared/ # Modulo KMP condiviso
│ ├── src/
│ │ ├── commonMain/kotlin/ # Logica condivisa
│ │ ├── commonTest/kotlin/ # Test condivisi
│ │ ├── androidMain/kotlin/ # Android-specific
│ │ └── iosMain/kotlin/ # iOS-specific
│ └── build.gradle.kts
├── androidApp/ # App Android
│ ├── src/main/...
│ └── build.gradle.kts
├── iosApp/ # App iOS (Xcode project)
│ ├── iosApp/
│ │ ├── ContentView.swift
│ │ └── iOSApp.swift
│ └── iosApp.xcodeproj
├── build.gradle.kts # Root (plugin declarations)
└── settings.gradle.kts # Moduli inclusi
Sonuçlar ve Sonraki Adımlar
Android, iOS ve paylaşılan modül ile eksiksiz bir KMP projesi oluşturdunuz. Eğri Gradle ve kaynak kümelerinin öğrenme eğrisi ilk başta diktir, ancak sahip olduğunuz yapı kurumsal projeler için oluşturulmuş, sağlam ve ölçeklenebilir.
Bir sonraki makale konuyu ele alıyorpaylaşılan modül mimarisi: daha karmaşık modeller için beklenti/gerçek nasıl kullanılır, bağımlılık için Koin nasıl ayarlanır çoklu platform enjeksiyonu ve kodun kolayca test edilebilecek şekilde nasıl yapılandırılacağı izolasyonda.
Seri: Kotlin Multiplatform — Tek Kod Tabanı, Tüm Platformlar
- Madde 1: 2026'da KMP - Mimarlık, Kuruluş ve Ekosistem
- Madde 2 (bu): İlk KMP Projesini Yapılandırma - Android, iOS ve Masaüstü
- Madde 3: Paylaşılan Modül Mimarisi - beklenen/gerçek, Arayüzler ve DI
- Madde 4: Ktor İstemcisi ile Çoklu Platform Ağ İletişimi
- Makale 5: SQLDelight ile Çoklu Platform Kalıcılığı
- Madde 6: Çoklu Platform Oluşturma — Android ve iOS'ta Paylaşılan Kullanıcı Arayüzü
- Madde 7: Durum Yönetimi KMP — ViewModel ve Kotlin Flows
- Madde 8: KMP Testi - Birim Testi, Entegrasyon Testi ve UI Testi
- Madde 9: Swift Export — iOS ile Deyimsel Birlikte Çalışma
- Madde 10: KMP Projeleri için CI/CD — GitHub Eylemleri ve Fastlane
- Madde 11: Örnek Olay İncelemesi - Üretimde KMP'li Fintech Uygulaması







