Skip to content
Learni
Voir tous les tutoriels
Kotlin

Comment créer un projet Kotlin Multiplatform en 2026

Read in English

Introduction

Kotlin Multiplatform (KMP) révolutionne le développement cross-platform en permettant de partager jusqu'à 90% du code Kotlin entre Android, iOS, desktop (JVM), web (JS) et serveur. Contrairement aux frameworks comme Flutter qui transpilents, KMP compile nativement pour chaque cible, offrant des performances optimales et un accès total aux APIs natives.

Pourquoi c'est crucial en 2026 ? Les apps hybrides explosent, mais la duplication de code coûte cher en maintenance. Avec KMP, centralisez votre logique métier (validation, calculs, data models) dans un module shared, et implémentez les spécificités via expect/actual.

Ce tutoriel beginner vous guide pour créer un projet minimal : une fonction platformName() partagée, exécutable sur JVM (console desktop) et compilable pour Android. À la fin, vous aurez un projet fonctionnel, prêt à scaler vers iOS. Temps estimé : 15 min. Analogie : comme un squelette commun avec des muscles adaptés à chaque sport.

Prérequis

  • IntelliJ IDEA Community (gratuit) ou Android Studio (pour émulateur Android optionnel)
  • JDK 21 installé (sdk install java 21-tem via SDKMAN ou téléchargement officiel)
  • Gradle 8.10+ (utilisé via wrapper, pas d'install manuel)
  • Terminal (bash/zsh sur Mac/Linux, Git Bash/PowerShell sur Windows)
  • Connaissances basiques de Kotlin (functions, packages)

Initialiser la structure du projet

terminal
mkdir my-kmp-project
cd my-kmp-project
gradle wrapper --gradle-version 8.10.2
mkdir -p shared/src/commonMain/kotlin/org/example
mkdir -p shared/src/jvmMain/kotlin/org/example
mkdir -p shared/src/androidMain/kotlin/org/example

Ce script crée le dossier racine, initialise Gradle wrapper pour reproductibilité, et génère la hiérarchie des source sets KMP : commonMain pour le code partagé, jvmMain pour desktop, androidMain pour mobile. Les packages org.example évitent les conflits. Lancez-le dans un terminal propre ; Gradle wrapper télécharge tout automatiquement.

Configurer settings.gradle.kts

Ce fichier centralise la gestion des modules et repositories. Il inclut le module shared et configure les dépôts pour Kotlin/Gradle. Ouvrez-le dans IntelliJ (File > Open > my-kmp-project) pour coloration syntaxique.

settings.gradle.kts (racine)

settings.gradle.kts
pluginManagement {
    repositories {
        google {
            content {
                includeGroupByRegex("com\\.android.*")
                includeGroupByRegex("com\\.google.*")
                includeGroupByRegex("androidx.*")
            }
        }
        mavenCentral()
        gradlePluginPortal()
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
    }
}
rootProject.name = "my-kmp-project"
include(":shared")

Configure les plugins et repositories pour éviter les conflits Android/Kotlin. FAIL_ON_PROJECT_REPOS force l'usage centralisé, réduisant les erreurs de résolution. include(":shared") déclare le module partagé. Copiez-collez tel quel ; il est optimisé pour Kotlin 2.0+.

Configurer build.gradle.kts racine

Le build racine définit les options globales comme le toolchain JVM. Il applique le plugin KMP sans le charger ici (délégué au module).

build.gradle.kts (racine)

build.gradle.kts
kotlin {
    jvmToolchain(21)
}

allprojects {
    tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
        kotlinOptions {
            jvmTarget = "21"
        }
    }
}

Définit JDK 21 globalement via jvmToolchain pour cohérence multiplateforme. Applique jvmTarget = "21" à tous les compiles Kotlin, évitant les warnings JVM. Minimaliste mais robuste ; étendez pour plus de modules.

Configurer le module shared

Cœur du KMP : ce build cible JVM (exécutable console) et Android (library). Il lie les source sets. Créez shared/build.gradle.kts.

build.gradle.kts (shared)

shared/build.gradle.kts
plugins {
    kotlin("multiplatform")
}

group = "org.example"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

kotlin {
    androidTarget()
    jvm {
        compilations.all {
            kotlinOptions.jvmTarget = "21"
        }
        withJava()
    }

    sourceSets {
        commonMain { }
        androidMain { }
        val jvmMain by getting { }
    }
}

tasks.register<org.gradle.process.JavaExec>("run") {
    group = "run"
    classpath = sourceSets["jvmMain"].runtimeClasspath
    mainClass.set("org.example.MainKt")
    standardInput = System.`in`
}

Applique plugin KMP, cible androidTarget() et jvm() pour deux plateformes. Source sets vides pour start minimal (ajoutez deps plus tard). Task run exécute le main JVM via classpath dynamique. Piège : sans withJava(), pas d'accès JAR.

Définir la fonction partagée (expect)

expect déclare l'API commune. Implémentez les actual par plateforme. Créez les fichiers aux chemins indiqués.

Platform.kt (commonMain)

shared/src/commonMain/kotlin/org/example/Platform.kt
package org.example

expect fun platformName(): String

Déclare expect fun : signature partagée, compilée partout. Kotlin vérifie que chaque plateforme a un actual matching. Simple comme un contrat ; étendez à classes, suspend funs ou generics.

PlatformJvm.kt (jvmMain)

shared/src/jvmMain/kotlin/org/example/PlatformJvm.kt
package org.example

actual fun platformName(): String {
    return "JVM (Desktop)"
}

actual implémente pour JVM. Retourne chaîne statique ; pour dynamique, utilisez System.getProperty("os.name"). Doit matcher exactement la signature expect, sinon erreur de link.

PlatformAndroid.kt (androidMain)

shared/src/androidMain/kotlin/org/example/PlatformAndroid.kt
package org.example

actual fun platformName(): String {
    return "Android"
}

actual pour Android : accédez à Build.MODEL si besoin après import android.os.Build. Compile en AAR réutilisable. Piège : pas d'accès JVM APIs ici (no System props natifs Android).

Ajouter le point d'entrée main

Pour tester sur JVM, ajoutez un main() consommant le code partagé. Utilisez-le comme library dans une app Android réelle.

main.kt (jvmMain)

shared/src/jvmMain/kotlin/org/example/main.kt
package org.example

fun main() {
    println("Bonjour depuis ${platformName()} !")
    println("Votre premier projet KMP fonctionne parfaitement.")
}

Top-level main() appelle platformName() partagé. S'exécute via ./gradlew run. Dans Android, importez org.example.platformName dans Activity/ViewModel. Fonctionne sans classes ; scalable à apps complexes.

Compiler et tester

Ouvrez le projet dans IntelliJ/Android Studio (auto-import Gradle). Vérifiez : pas d'erreurs rouges.

Build et exécution

terminal
cd my-kmp-project
./gradlew clean build
./gradlew run

# Vérifiez Android compile
./gradlew compileKotlinAndroid

clean build compile toutes cibles (JVM JAR + Android classes). run lance console : "Bonjour depuis JVM (Desktop) !". compileKotlinAndroid valide Android sans émulateur. Succès = KMP prêt ! Temps : <1min.

Bonnes pratiques

  • Toujours expect/actual pour APIs plateforme-spécifiques (fichiers, réseau) ; gardez pure functions en commonMain.
  • Ajoutez deps communes (kotlinx.coroutines en commonMain) pour async partagé.
  • Utilisez compose.multiplatform pour UI partagée après ce basique.
  • Versionnez Kotlin/Gradle fixes ; testez multi-OS via Gradle checks.
  • Structurez : models/data en common, UI/impls en plateforme.

Erreurs courantes à éviter

  • Pas d'actual : erreur link-time "Unsatisfied expectation". Vérifiez source sets paths.
  • Mauvais jvmTarget : Mismatch JDK cause NoClassDefFound. Forcez 21 partout.
  • Repositories manquants : Google() pour Android deps ; ajoutez snapshot si Kotlin nightly.
  • MainClass erroné : Utilisez MainKt pour top-level (pas "main"). Debug via --stacktrace.

Pour aller plus loin