Publication de Kotlin 1.4-M2

Publié le par Delphine Massenhove

Le temps passe vite et nous vous présentons déjà en avant-première plusieurs nouvelles fonctionnalités particulièrement puissantes de Kotlin 1.4. Découvrez ce que Kotlin 1.4-M2 vous réserve, essayez-la et profitez de ses fonctionnalités avant le lancement officiel de Kotlin 1.4.

kotlin-1.4-M2

Nous remercions tous ceux qui ont essayé notre première version preview de Kotlin 1.4, nous ont fait part de leurs commentaires et contribué à améliorer Kotlin !

Un grand merci également à ceux qui ont déjà testé les améliorations de la bibliothèque standard de Kotlin 1.4-M2 annoncées dans notre précédent article de blog.

Dans cet article, nous présentons les nouvelles fonctionnalités et principales améliorations apportées par la version 1.4-M2 :

  • La prise en charge du partage de code dans plusieurs cibles grâce à la structure hiérarchique dans les projets multiplateformes.
  • Un nouvel assistant de projet Kotlin flexible pour créer et configurer facilement différents types de projets.
  • Un nouveau mode de compilation pour les auteurs de bibliothèques, appelé mode API explicite, qui permet de créer des API cohérentes et bien décrites.
  • La prise en charge par Kotlin/Native de l’utilisation des fonctions de suspension de Swift et Objective-C.
  • Le Gradle DSL de Kotlin/JS amelioré, la prise en charge directe de CSS et une annotation d’exportation commune.

Vous trouverez la liste complète des changements apportés dans le journal des modifications.

Nous comptons sur vous pour essayer la preview et nous faire part de vos retours.

Partager du code dans plusieurs cibles grâce à la structure hiérarchique du projet

Grâce à la nouvelle structure hiérarchique du projet, vous pouvez partager du code entre plusieurs cibles dans un projet multiplateforme.

Auparavant, tout code ajouté à un projet multiplateforme pouvait être placé soit dans un jeu de sources spécifique à une plateforme, qui est limité à une cible et ne peut être réutilisé par aucune autre plateforme, soit dans un jeu de sources commun, tel que commonMain ou commonTest, qui est partagé entre toutes les plateformes du projet. Dans le jeu de sources commun, vous ne pouviez appeler une API spécifique à une plateforme qu’en utilisant une déclaration expect, qui nécessite des implémentations actual spécifiques à la plateforme.

Cela facilitait le partage de code entre toutes les cibles, mais il n’était pas si facile de le faire entre certaines cibles seulement, en particulier les cibles similaires qui pouvaient potentiellement réutiliser une grande partie de la logique commune et des API tierces.

Par exemple, dans un projet multiplateforme typique ciblant iOS, il y a deux cibles liées à iOS : une pour les appareils iOS ARM64 et l’autre pour le simulateur x64. Ils ont des jeux de sources séparés, spécifiques à la plateforme, mais en pratique, il est rarement nécessaire d’avoir un code différent pour l’appareil et le simulateur et leurs dépendances sont très similaires. Le code spécifique à iOS pourrait donc être partagé entre eux.

Apparemment, dans cette configuration, il serait souhaitable d’avoir un jeu de sources partagées pour deux cibles iOS, avec du code Kotlin/Native qui pourrait toujours appeler directement n’importe laquelle des API communes pour l’appareil iOS et le simulateur.

ios-source-sets

Vous pouvez maintenant le faire grâce à la prise en charge de la structure hiérarchique du projet, qui déduit et adapte les fonctionnalités de l’API et du langage disponibles dans chaque jeu de sources en fonction des cibles qui les utilisent.

Comment l’utiliser

Installez le plugin Kotlin 1.4 M2 incluant la prise en charge hiérarchique du projet dès maintenant !

Ajoutez l’indicateur suivant au fichier gradle.properties de votre projet :

Veuillez noter que la structure hiérarchique, ainsi que tous les projets multiplateformes, nécessitent Gradle 6.0 ou une version ultérieure à compter de Kotlin 1.4-M2.

Vous pouvez créer une structure hiérarchique avec des raccourcis de cible disponibles pour des scénarios multicibles typiques ou manuellement en connectant les jeux de sources.

Par exemple, créez les deux cibles iOS et le jeu de sources partagées présenté ci-dessus avec le raccourci ios() :

Pour d’autres combinaisons de cibles, créez une hiérarchie manuellement en reliant les jeux de sources à la relation dependOn.

desktopMain-hierarchy

Vous pouvez définir un jeu de sources partagées pour les combinaisons de cibles suivantes :

  • JVM + JS + Native
  • JVM + Native
  • JS + Native
  • JVM + JS
  • Natifs

Pour l’instant, nous ne prenons pas en charge le partage d’un jeu de sources pour ces combinaisons :

  • Multiples cibles JVM
  • Cibles Android + JVM
  • Multiples cibles JS

N’hésitez pas à nous faire part de vos combinaisons de cibles par e-mail à l’adresse feedback@kotlinlang.org. Cela nous permettra de prioriser les combinaisons les plus courantes.

Partager du code dans les bibliothèques

Grâce à la structure hiérarchique du projet, les bibliothèques peuvent également fournir des API communes pour un sous-ensemble de cibles.

Lorsqu’une bibliothèque est publiée, l’API de ses jeux de sources partagés est intégrée aux artefacts de la bibliothèque, avec les informations sur la structure du projet. Lorsque vous utilisez cette bibliothèque, les jeux de sources partagés de votre projet accèdent précisément aux API de la bibliothèque disponibles pour les cibles de chaque jeu de sources.

Par exemple, consultez la hiérarchie suivante des jeux de sources dans la branche native-mt du référentiel kotlinx.coroutines :

coroutines-hierarchy

Le jeu de sources commun déclare la fonction runBlocking et est compilé pour la JVM et les cibles natives. Vous pouvez vous en servir et appeler runBlocking() à partir d’un jeu de sources partagé entre une cible JVM et des cibles natives, puisqu’il concorderait avec la “signature des cibles” du jeu de sources concurrent de la bibliothèque.

Spécifier les dépendances une seule fois

Désormais, au lieu de spécifier des dépendances sur différentes variantes de la même bibliothèque dans les jeux de sources partagés et spécifiques à la plateforme où elle est utilisée, vous ne devez spécifier une dépendance qu’une seule fois dans le jeu de sources partagées.

N’utilisez pas les noms d’artefacts de la bibliothèque kotlinx avec des suffixes spécifiant la plateforme, tels que -common, -native ou autre, car ils ne sont plus pris en charge. À la place, utilisez le nom de l’artefact de base de la bibliothèque, qui dans l’exemple ci-dessus est kotlinx-coroutines-core. Cependant, le changement n’affecte pas actuellement les bibliothèques stdlib et kotlin.test (stdlib-common et test-common) ; elles seront modifiées ultérieurement.

Si vous avez besoin d’une dépendance uniquement pour une plateforme spécifique, vous pouvez toujours utiliser des variantes spécifiques à la plateforme des bibliothèques standards et kotlinx avec des suffixes tels que -jvm ou -js, comme par exemple kotlinx-coroutines-core-jvm.

Tirer parti des bibliothèques natives dans la structure hiérarchique

Vous pouvez utiliser des bibliothèques dépendantes de la plateforme, telles que Foundation, UIKit et posix, dans des jeux de sources partagés entre plusieurs cibles natives. Cela permet de partager davantage de code natif sans être limité par des dépendances spécifiques à la plateforme.

Aucune étape supplémentaire n’est nécessaire, tout se fait automatiquement. IntelliJ IDEA vous aidera à détecter les déclarations communes que vous pouvez utiliser dans le code partagé.

Il y a cependant certaines limites :

  • Cette approche ne fonctionne que pour un jeu de sources natif qui est partagé entre des jeux de sources spécifiques à la plateforme. Cela ne fonctionne pas pour les jeux de sources natifs partagés à des niveaux plus élevés de la hiérarchique du jeu de sources.
    Par exemple, si vous avez nativeDarwinMain qui est parent de watchosMain et iosMain, où iosMain a deux enfants – iosArm64Main et iosX64Main, vous pouvez utilisez des bibliothèques dépendantes de la plateforne pour iosMain seulement, mais pas pour nativeDarwinMain.
  • Cette approche ne fonctionne que pour les bibliothèques interopérables fournies avec Kotlin/Native.

En savoir plus sur les détails techniques.

Comment l’utiliser

Pour permettre l’utilisation de bibliothèques dépendantes de la plateforme dans des jeux de sources partagés, ajoutez ce qui suit à votre gradle.properties :

Donner votre avis sur la structure hiérarchique

La structure hiérarchique du projet est actuellement en phase de preview technologique et toujours en cours de développement. Vous pouvez consulter les problèmes connus que nous allons résoudre, dont certains ont des solutions provisoires.

N’hésitez pas à demander de l’aide sur le canal \#multiplateform Slack de Kotlin et à signaler les bugs sur YouTrack, notre outil de suivi. Il s’agit d’une fonctionnalité complexe et importante, vos commentaires seront donc particulièrement utiles !

Gradle 6.0 ou ultérieur requis dans les projets multiplateformes

À compter de Kotlin 1.4-M2, tous les projets multiplateformes nécessitent Gradle 6.0 ou une version ultérieure. Veuillez vous assurer de mettre à jour Gradle pour vos projets utilisant le plugin kotlin-multiplatform.

Un nouvel assistant de projet flexible

Grâce au nouvel assistant de projet Kotlin flexible, vous disposez d’un endroit unique où vous pouvez facilement créer et configurer des projets Kotlin de différents types, y compris des projets multiplateformes, qui sont en général assez difficiles à configurer sans interface utilisateur.

project-wizard-1

Auparavant, vous pouviez créer des projets Kotlin à partir de différents emplacements qui offraient plusieurs options de configuration. Désormais, il n’y a plus qu’un seul emplacement pour le faire, alliant simplicité et flexibilité :

  1. Sélectionnez le modèle de projet en fonction de ce que vous désirez faire.
  2. Sélectionnez le système de build : Gradle (Kotlin ou Groovy DSL), Maven ou IntelliJ. L’assistant ne propose que les systèmes de build pris en charge pour le modèle de projet sélectionné.
  3. Prévisualisez la structure du projet directement sur l’écran principal.

Vous pouvez ensuite terminer la création de votre projet ou, éventuellement, configurer le projet sur l’écran suivant :

  1. Ajoutez ou supprimez des modules et des cibles pris en charge pour ce modèle de projet.
  2. Configurez les paramètres des modules et des cibles, par exemple, la version JVM cible, le modèle cible et le framework de tests.

project-wizard-2

  1. Définissez les dépendances des modules entre :
    • modules iOS et multiplateformes
    • Modules Android et multiplateformes
    • Modules JVM

project-wizard-3

À l’avenir, l’assistant de projet Kotlin sera encore plus adaptable grâce à de nouvelles options de configuration et de nouveaux modèles.

Comment l’utiliser

  1. Installez le plugin Kotlin 1.4-M2.
  2. Dans IntelliJ IDEA, cliquez sur File | New | Project.
  3. Dans le panneau de gauche, sélectionnez Kotlin (Experimental Wizard).
  4. Créez votre projet Kotlin.

Des API cohérentes et mieux décrites avec un mode API explicite

Nous introduisons un nouveau mode de compilation pour aider les auteurs de bibliothèques à créer des API cohérentes et bien décrites. Dans ce mode API explicite, le compilateur effectue des vérifications supplémentaires sur les déclarations exposées à l’API publique de la bibliothèque :

  • Des modificateurs de visibilité sont nécessaires pour les déclarations si la visibilité par défaut les expose à l’API publique. Cela permet de s’assurer qu’aucune déclaration n’est exposée publiquement de manière involontaire.
  • Des spécifications de type explicites sont requises pour les propriétés et les fonctions qui sont exposées à l’API publique. Ainsi, les utilisateurs de l’API sont informés des types de membres de l’API qu’ils utilisent.

explicity-api-mode

Selon votre configuration, ces contrôles peuvent produire des erreurs (mode strict) ou des avertissements (mode warning).

Nous prévoyons d’ajouter d’autres contrôles à l’avenir afin d’améliorer votre expérience d’auteur de bibliothèque. Découvrez-en davantage à ce sujet dans ce KEEP. Mais vous pouvez déjà essayer le mode API explicite et nous faire part de vos commentaires.

Pour compiler votre module en mode API explicite, ajoutez l’une des lignes suivantes à votre script de build Gradle :

Dans Groovy, vous pouvez utiliser la syntaxe alternative ci-dessous :

Lorsque vous utilisez le compilateur en ligne de commande, utilisez l’option du compilateur -Xexplicit-api, soit avec strict, soit avec warning :

Prise en charge par Kotlin/Native de la suspension des fonctions et autres améliorations

Dans cette preview, nous avons enfin ajouté la prise en charge des fonctions de suspension de Kotlin pour Swift et Objective-C, qui ne couvre pour l’instant que les cas basiques. Nous continuons à travailler pour vous donner toute la puissance des coroutines dans les applications Swift et Objective-C. Par ailleurs, nous sommes prêts à présenter certains résultats de notre travail sur les performances et la stabilité de Kotlin/Native.

Prise en charge des fonctions de suspension de Kotlin pour Swift et Objective-C

Nous continuons à développer la prise en charge de l’utilisation des principales fonctionnalités de Kotlin depuis du code Swift et Objective-C. L’un des inconvénients connus des versions précédentes était leur prise en charge incomplète des coroutines Kotlin : les fonctions de suspension n’étaient pas disponibles depuis du code Swift ou Objective-C.

Dans la preview M2, nous avons le plaisir de vous présenter la prise en charge basique des fonctions de suspension dans Swift et Objective-C. Désormais, lorsque vous compilez un module Kotlin dans un framework Apple, les fonctions de suspension y sont disponibles comme des fonctions avec rappels (completionHandler dans la terminologie Swift/Objective-C). Lorsque vous disposez de telles fonctions dans l’en-tête du framework généré, vous pouvez les appeler à partir de votre code Swift ou Objective-C et même les ignorer.

Par exemple, si vous écrivez cette fonction Kotlin :

…alors vous pouvez l’appeler ainsi depuis Swift :

Veuillez noter que dans la preview M2 vous ne pouvez appeler la fonction de suspension que depuis le thread principal.

Exécuter du code Kotlin/Native grâce à l’icône de gouttière

Auparavant, vous ne pouviez exécuter du code Kotlin/Native que dans le Terminal ou en exécutant une tâche Gradle dans IntelliJ IDEA. Vous pouvez maintenant l’exécuter facilement grâce à l’icône de gouttière, comme pour tout code Kotlin.

native-gutter-icon

Amélioration des performances pour l’interopérabilité C

Afin d’améliorer les performances de Kotlin/Native, nous avons retravaillé la manière dont les bibliothèques C interopérables sont construites. (Ces bibliothèques sont des artefacts qui vous permettent d’utiliser les déclarations des bibliothèques C et Objective-C depuis le code Kotlin.) Les changements se font en coulisse, mais ce qui est visible, c’est l’augmentation des performances et la réduction des artefacts : les nouveaux outils produisent des bibliothèques interopérables jusqu’à 4 fois plus vite qu’auparavant et les artefacts font 25 à 30% de leur taille d’origine !

L’utilisation de bibliothèques interopérables est désormais plus rapide car la compilation des projets Kotlin en C interopérable prend moins de temps avec Kotlin 1.4-M2.

Stabilisation de la mise en cache du compilateur et de l’utilisation du démon Gradle

Dans la version 1.3.70, nous avons introduit deux nouvelles fonctionnalités pour améliorer les performances de la compilation Kotlin/Native : la mise en cache des dépendances du projet et l’exécution du compilateur à partir du démon Gradle. Celles-ci étant toujours en cours de développement, certains d’entre vous ont pu rencontrer des problèmes et un manque de stabilité dans certains cas.

Grâce à vos retours, nous avons réussi à corriger de nombreux problèmes et à améliorer la stabilité globale de ces fonctionnalités. Donc, si vous avez eu des problèmes avec elles, ou si vous n’avez pas eu l’occasion de tester les dernières versions de Kotlin/Native, c’est le moment idéal pour essayer.

Améliorations de Kotlin/JS

Avec la version 1.4-M2, la cible JavaScript de Kotlin aligne plus étroitement ses conventions de nommage Gradle avec celles des autres cibles de Kotlin. Elle permet également de contrôler plus finement les paramètres du compilateur, de normaliser l’annotation @JsExport et d’activer par défaut la prise en charge du CSS par webpack.

Modifications de Gradle DSL

Changements de dénomination

Pour nous aligner plus étroitement sur les autres cibles de Kotlin, nous avons changé les noms de certains éléments couramment utilisés de la configuration Gradle de Kotlin/JS. Considérons ce bloc de configuration par défaut pour un projet Gradle Kotlin/JS en 1.4-M2, qui illustre les deux changements de dénomination que nous avons effectués :

  • target devient js, ce qui le rend cohérent vis-à-vis de la syntaxe utilisée avec le plugin Kotlin multiplateforme.
  • produceExecutable(), introduit dans Kotlin 1.4-M1, devient binaries.executable(), ce qui le rend cohérent avec la dénomination utilisée pour Kotlin/Native.

Si vous souhaitez en savoir plus sur ce que fait binaries.executable(), veuillez vous référer à l’article de blog sur la version 1.4-M1, section “Kotlin/JS | Modifications de Gradle DSL.

Paramètres de compilateur par projet

Avec Kotlin 1.4-M1, nous avons notamment lancé le nouveau backend du compilateur IR avec un DCE optimisé, l’aperçu des déclarations TypeScript, et un réglage dans gradle.properties pour basculer entre les modes par défaut, IR, et les deux modes du compilateur. La preview M2 propose un contrôle plus fin du mode de compilation utilisé pour chaque projet, directement à partir de la configuration de Gradle.

Pour passer d’un mode de compilateur à l’autre, passez un type de compilateur à la fonction js dans votre script de build Gradle. Par exemple :

Le réglage du type de compilateur pour un projet comme celui-ci remplace le réglage par défaut spécifié dans gradle.properties.

Prise en charge du css-loader pour webpack de Gradle

Comme le plugin Kotlin/JS Gradle utilise webpack par défaut pour créer des artefacts pour le navigateur, il existe de nombreux paramètres qui peuvent être personnalisés. Bien que toutes les options puissent être modifiées en changeant directement les fichiers de configuration webpack qui sont utilisés pour construire votre projet, nous voulons donner accès aux paramètres les plus couramment utilisés directement via Gradle DSL.

Kotlin 1.4-M2 active par défaut le css-loader de webpack pour les projets ciblant le navigateur. Cela signifie que l’ajout de CSS à votre projet, ainsi que de dépendances comprenant des feuilles de style, fonctionnera désormais sans problème dans la plupart des cas, sans configuration supplémentaire. Auparavant, vous avez pu rencontrer des erreurs telles que Module parse failed: Unexpected character '@' (14:0) dans de telles situations.

Si vous souhaitez ajuster le comportement de cette intégration CSS, vous pouvez le faire en utilisant js.browser.webpackTask.cssSettings.

Avec cssSettings.enabled, vous pouvez déterminer si votre projet doit utiliser css-loader (activé par défaut).

Avec cssSettings.mode, vous pouvez spécifier comment tout CSS rencontré doit être traité. Les valeurs suivantes sont disponibles :

  • "inline" (par défaut) : les styles sont ajoutés à la balise <style> globale.
  • "extract" : les styles sont extraits dans un fichier séparé. Ils peuvent ensuite être inclus à partir d’une page HTML.
  • "import" : les styles sont traités comme des chaînes. Cela peut être utile si vous avez besoin d’accéder au CSS à partir de votre code (par exemple val styles = require("main.css")).

Si vous souhaitez utiliser différents modes pour le même projet, vous pouvez utiliser cssSettings.rules. Ici, vous pouvez spécifier une liste de KotlinWebpackCssRules, dont chacune définit un mode, ainsi que des modèles d’inclusion et d’exclusion. Pour en savoir plus sur ces modèles, consultez la documentation webpack sur les règles d’inclusion et d’exclusion.

Nom de module personnalisable

Vous pouvez maintenant changer le nom du module JavaScript directement à partir du script de build Gradle :

Cela change le nom du module généré dans build/js/packages/myModuleName, y compris les noms de fichiers .js et .d.ts correspondants. Veuillez noter que cela n’affecte pas votre sortie webpack dans build/distributions. Pour changer le nom du fichier webpack, vous pouvez utiliser js.browser.webpackTask.outputFileName.

Annotation @JsExport en code commun

L’annotation @JsExport, que vous pouvez utiliser pour rendre une déclaration de haut niveau disponible depuis JavaScript ou TypeScript lorsque vous utilisez le backend du compilateur IR, est maintenant disponible en code commun. Ainsi, il n’est plus nécessaire d’introduire une annotation et des typealias personnalisés, et cela ouvre la voie pour la construction pratique de bibliothèques JavaScript à partir de projets Kotlin multiplateformes.

Autres améliorations et correctifs notables

  • Les tâches Gradle utilisées pour les opérations typiques du navigateur et des cibles nodejs sont maintenant regroupées dans des groupes de tâches séparés. Les groupes kotlin browser et kotlin node apparaîtront dans la fenêtre d’outil Gradle dans IntelliJ IDEA ou lorsque vous listerez les tâches via ./gradlew tasks --all.
  • Lors de l’exécution de tests pour la cible node.js, le débogueur s’arrête désormais correctement aux points de rupture.
  • Pour les projets et les bibliothèques utilisant le mode both pour la compilation, les dépendances klib sont maintenant correctement résolues.

Compatibilité

Notez que Kotlin 1.4 n’est pas rétrocompatible avec la version 1.3 dans certains cas particuliers. Tous ces cas ont été soigneusement examinés par le comité du langage et seront répertoriés dans le “guide de compatibilité” (similaire à celui-ci). Pour le moment, vous pouvez trouver cette liste dans YouTrack.

Notes de pré-version

Notez que les garanties de rétrocompatibilité ne concernent pas les versions préliminaires. Les fonctionnalités et l’API peuvent changer dans les versions ultérieures. Lorsque nous atteindrons un RC final, tous les binaires produits par les versions préliminaires seront interdits par le compilateur et vous devrez recompiler tout ce qui a été compilé par la version 1.4 ‑ Mx.

Comment essayer les dernières fonctionnalités

Comme toujours, vous pouvez essayer Kotlin en ligne sur play.kotl.in.

Dans IntelliJ IDEA et Android Studio, vous pouvez mettre à jour le plugin Kotlin vers la version 1.4-M1. Voir comment procéder.

Si vous souhaitez travailler sur des projets existants qui ont été créés avant d’installer la version préliminaire, vous devez configurer votre build pour la version Prewiew dans Gradle ou Maven.

Vous pouvez télécharger le compilateur de ligne de commande sur la page de la version sur Github.

Vous pouvez utiliser les versions suivantes des bibliothèques publiées avec cette version du langage :

Les détails de la version et la liste des bibliothèques compatibles sont également disponibles ici.

Faites-nous part de vos commentaires

Nous vous serions très reconnaissants de nous signaler les bugs via notre outil de suivi. Nous ferons de notre mieux pour résoudre tous les problèmes importants avant la version finale, afin que vous n’ayez pas à attendre la prochaine version de Kotlin.

Nous vous invitons à rejoindre le canal \#eap sur le Slack Kotlin (demandez une invitation ici). Sur ce canal, vous pouvez poser vos questions, participer aux discussions et recevoir es notifications sur les builds des previews.

Faison évoluer Kotlin ensemble !

Contributions externes

Nous remercions tous nos contributeurs externes dont les requêtes pull ont été incluses dans cette version :

Auteur de l’article original en anglais : Ekaterina Volodko