Kotlin 1.4-M2 リリース

Elizaveta Semakova

あっという間に、次の Kotlin 1.4 の強力な機能をいくつか紹介する日がやってきました。 Kotlin 1.4 として正式にリリースされる前に、Kotlin 1.4-M2 の新機能と強化機能を確認し、それらを試してお楽しみください。

kotlin-1.4-M2

Kotlin 1.4 の最初のプレビューを試してフィードバックをご提供いただいた皆さん、ありがとうございました。Kotlinの改善に大きく役立たせていただきました!

また、この記事 (英語)で発表した Kotlin 1.4-M2 の標準ライブラリの改善機能をすでに試していただいた方にも、お礼を申し上げたいと思います。

この記事では、1.4-M2 の新機能と主な改善点について紹介します。

完全な変更リストは変更ログで確認できます。 これまで同様、社外貢献者の皆様からのご協力に深く感謝いたします。

ぜひプレビューをお試しの上、フィードバックをお寄せください

 

階層プロジェクト構造により複数ターゲットのコードを共有

新しい階層プロジェクト構造のサポートにより、マルチプラットフォームプロジェクトの複数のターゲット間でコードを共有できるようになりました。

以前は、マルチプラットフォームプロジェクトに追加されたコードはすべて、プラットフォーム固有のソースセットか共通のソースセットにいずれかに配置されていました。ただし、プラットフォーム固有のソースセットの場合は、1つのターゲットに制限されるため、ほかのプラットフォームが再利用することができませんでした。一方、commonMain や commonTest といった共通ソースセットの場合は、プロジェクト内のすべてのプラットフォームに共有されてしまうという欠点がありました。 プラットフォーム固有の API を呼び出すには、プラットフォーム固有の actual 実装が必要となる expect 宣言を使うしかなかったのです。

このため、すべてのターゲット間でコードを共有するのは簡単でしたが、一部に限定して共有するのはそれほど簡単なことではありませんでした。特に、多数の共通ロジックとサードパーティ API を再利用する可能性のある似たようなものであれば、尚更です。

たとえば、iOS をターゲットとした一般的なマルチプラットフォームプロジェクトには、iOS ARM64 系デバイスと x64 シミュレーターの2種類の iOS 関連ターゲットがあります。 それぞれに個別のプラットフォーム固有のソースセットがありますが、実際のところ、デバイスとシミュレーターに別々のコードを用意する必要はほとんどなく、依存ファイルについても同じことが言えます。 つまり、iOS 固有のコードをこれら2つのターゲットで共有することも可能なのです。

この条件では明らかに、2つの iOS ターゲットで共有ソースセットを使用し、さらに iOS デバイスとシミュレーターの両方に共通する任意の API を直接呼び出せる Kotlin/Native コードを使用できるのが理想的だと言えます。

ios-source-sets

これは、階層プロジェクト構造のサポートによって実現できるようになりました。使用されるターゲットに基づいて、各ソースセットに存在する API と言語機能を推論して適合させています

使用方法

階層プロジェクトをサポートする 1.4-M2 Kotlin プラグインを今すぐインストールしましょう!

プロジェクトの gradle.properties ファイルに次のフラグを追加します。

なお、Kotlin 1.4-M2 以降、階層構造だけでなく、すべてのマルチプラットフォームには Gradle 6.0 が必要です。

階層構造は、一般的なマルチターゲットのシナリオに用意されたターゲットショートカットを使って、またはソースセットを接続して手動で作成できます。

たとえば、ios()  ショートカットを使用して、上に示すように2つの iOS ターゲットと共有ソースセットを作成します。

他のターゲットの組み合わせについては、dependsOn リレーションを使ってソースセットを接続し、手動で作成します。

desktopMain-hierarchy

次のターゲットの組み合わせで共有ソースセットを使用できます。

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

現時点では、次の組み合わせにはソースセットの共有をサポートしていません。

  • 複数の JVM ターゲット
  • JVM + Android ターゲット
  • 複数の JS ターゲット

ご希望のターゲットの組み合わせをぜひメールでお知らせください(feedback@kotlinlang.org)。 どの組み合わせがより一般的に使用されているのかがわかれば、対応を優先付けやすくなります。

ライブラリのコードを共有

階層プロジェクト構造により、ライブラリもターゲットのサブセットに対して共通 API を適用できるようになります。

ライブラリが公開されると、その共有ソースセットの API は、プロジェクト構造に関する情報とともにライブラリアーティファクトに組み込まれます。 このライブラリを使用する際、プロジェクトの共有ソースセットは、各ソースセットのターゲットで利用できるライブラリのAPIに正確にアクセスします。

たとえば、kotlinx.coroutines リポジトリの native-mt ブランチにある次のソースセット階層を見てみましょう。

coroutines-hierarchy

concurrent ソースセットは、runBlocking 関数を宣言した上で、JVMとネイティブターゲット向けにコンパイルされます。 ライブラリの concurrent ソースセットの「ターゲットシグネチャー」と一致するため、安心してJVMターゲットとネイティブターゲットが共有するソースファイルから runBlocking() を呼び出すことができます。

依存関係の指定は一度きり

これからは、同一ライブラリの別バージョンへの依存を、共有ソースセットとプラットフォーム固有のソースセットに指定する代わりに、共有ソースセットに一度だけ指定するだけでよくなります。

Kotlinx ライブラリアーティファクト名には、 -common-native のようなプラットフォームを指定する接尾辞を使わないようにしてください。これらのサポートは終了しています。 代わりに、ライブラリベースアーティファクト名を使用してください。上の例では、kotlinx-coroutines-core です。 この変更は現在 stdlibkotlin.test ライブラリ(stdlib-common and test-common)には影響しませんが、それについても後で解決される予定です。

特定のプラットフォームに限定して依存関係が必要な場合は、標準ライブラリとkotlinxライブラリのプラットフォーム固有のバリアントに -jvm or -js などの接尾辞を使用できます。例えば、kotlinx-coroutines-core-jvm とすることができます。

階層構造におけるネイティブライブラリの活用

複数のネイティブターゲットで共有されるソースセットに、FoundationUIKitposix といったプラットフォーム依存ライブラリを使用できます。 このため、プラットフォーム固有の依存関係に制限されることなくより多くのネイティブコードを共有できます。

特別な手順は必要なく、すべて自動的に行われます。 IntelliJ IDEA において、共有コードで使用できる共通宣言が検出されます。

ただし、いくつかの制限があることに注意してください。

  • このアプローチは、プラットフォーム固有のソースセットで共有されているネイティブソースセットでのみ機能します。 ソースセット階層より上位で共有されているネイティブソースセットでは機能しません。
    たとえば、 watchosMainiosMain の親である nativeDarwinMain があり、iosMain にはさらに iosArm64MainiosX64Main という子が2つある場合、iosMain にはプラットフォーム依存ライブラリを使用できますが、nativeDarwinMain には使用できません。
  • このアプローチは、Kotlin/Native に含まれる相互運用機能(interop)ライブラリでのみ機能します。

技術的な詳細について、さらにお読みください。

使用方法

共有ソースセットのプラットフォーム依存ライブラリを使用できるようにするには、gradle.properties に次を追加してください。

階層構造に関するフィードバックをお待ちしています

階層プロジェクト構造は現在、技術的なプレビューであり開発段階にあります。 修正が予定されている既知の課題についてもご確認ください。一部には回避策も用意されています。

Kotlin Slack の \#multiplatformチャンネル で、ぜひご質問ください。また、課題トラッカー YouTrack へのバグの報告もお待ちしています。 これは複雑で大きなインパクトのある機能であるため、皆さんからのフィードバックが特に役立ちます!

マルチプラットフォームプロジェクトには Gradle 6.0 以降が必要

Kotlin 1.4-M2 より、すべてのマルチプラットフォームプロジェクトには Gradle 6.0 以降が必要となります。 kotlin-multiplatform プラグインを使用するプロジェクトの Gradle を必ずアップグレードしてください。

柔軟性の高い新しいプロジェクトウィザード

柔軟性の高い新しい Kotlin プロジェクトウィザードの導入により、1つの画面から、様々なタイプの Kotlin プロジェクトを簡単に作成および構成できるようになりました。もはや、UI なしでは構成が困難になりがちなマルチプラットフォームプロジェクトもここで構成可能です。

project-wizard-1

以前、Kotlin プロジェクトの作成は、異なる構成オプションが用意された様々な場所で行われていました。 これからは、この操作を1つ場所に集約して簡便化するとともに、柔軟性を与えています。

  1. 作業目的に合った プロジェクトテンプレートを選択 します。
  2. ビルドシステムを選択 します。Gradle(Kotlin または Groovy DSL)、Marven、または IntelliJ を選べます。 ウィザードには選択したプロジェクトテンプレートでサポートされているビルドシステムのみが表示されます。
  3. メイン画面の右側で直接プロジェクト構造をプレビューします。

ここでプロジェクトの作成を終了するか、オプションとして次の画面に進み、プロジェクトを構成することができます。

  1. このプロジェクトテンプレートでサポートされているモジュールとターゲットを追加 / 削除できます。
  2. モジュールとターゲットの設定を構成できます。たとえば、ターゲット JVM バージョン、ターゲットテンプレート、テストフレームワークなどです。

project-wizard-2

  1. 次のモジュール依存関係を設定します。
    • iOSとマルチプラットフォームモジュール
    • Androidとマルチプラットフォームモジュール
    • JVMモジュール

project-wizard-3

将来的には、構成オプションとテンプレートをさらに追加し、Kotlin プロジェクトウィザードの柔軟性をさらに高める予定です。

使用方法

  1. 1.4-M2 Kotlin プラグインをインストールします。
  2. IntelliJ IDEAで、ファイル | 新規 | プロジェクトをクリックします。
  3. 左側のパネルで、Kotlin (Experimental Wizard)(実験的ウィザード)を選択します。
  4. 新しいKotlinプロジェクトを作成します。

Explicit APIモードによる、しっかりと記述された一貫性のある API

ライブラリ作成者がしっかりと記述された一貫性のある API を作成できるように、新しいコンパイラモードを導入しています。 Explicit API モードでは、コンパイラはライブラリの public API として公開される宣言に追加の検証を実行します。

  • デフォルトの可視性(Visibility)を使用してpublic な API を公開しようとすると、宣言に対して可視性修飾子の指定が必須になります。 これにより、ある宣言を誤って public として公開することがなくなります。
  • public API により公開されるプロパティと関数には明示的な型の指定が必須になります。 これにより、API ユーザーがどの型の API メンバーを使用しているかを認識できます。

explicity-api-mode

構成により、これらの確認でエラー(strict(厳格)モード)または警告(warning(警告)モード)を発生させることができます。

ライブラリの作成体験を改善できるように、将来的に、検証をさらに追加する予定です。 これについては、こちらの KEEP でさらに詳しくお読みください。 Explicit API モードをすぐに試すことができます。ぜひフィードバックをお寄せください。

Explicit API モードでモジュールをコンパイルするには、Gradle ビルドスクリプトに次のいずれかの行を追加してください。

Groovyでは、別の構文を使用できます。

command-line コンパイラを使用している場合は、 -Xexplicit-api コンパイラオプションを strict または warning にして使用してください。

サスペンド関数とその他の強化機能の Kotlin/Native サポート

このプレビューでは、Swift と Objective-C における Kotlin のサスペンド関数のサポートがようやく追加されました。ただし、現時点でカバーされるのは基本的なケースのみです。 私たちは、Swift と Objective-C アプリケーションでコルーチンの性能を全開できるように改善を続けています。 一方、Kotlin/Native のパフォーマンスと安定性への取り組みについて、その成果を一部発表できるようになりました。

SwiftとObjective-C における Kotlin のサスペンド関数のサポート

Swift と Objective-C コードから主な Kotlin 機能を使用するためのサポートを拡大し続けています。 既知の制約として、これまでバージョンでは、Kotlinコルーチンのサポートが不完全であることがありました。サスペンド関数がSwiftまたはObjective-Cコードから使用できなかったのです。

M2 プレビューでは、Swift と Objective-C におけるサスペンド関数の基本サポートを提供できるようになりました。 Kotlin モジュールを Apple フレームワークにコンパイルする場合、コールバック(Swift/Objective-C 用語では completionHandler)の関数としてサスペンド関数をフレームワークで使用できます。 生成されたフレームワークのヘッダーにこの関数がある場合、Swift または Objective-C コードから呼び出し、オーバーライドすることもできます。

たとえば、このKotlin関数を記述した場合:

Swift から次のように呼び出すことができます:

ただし、M2 プレビューでは、サスペンド関数を呼び出しは、メインスレッドからのみに限定されることにご注意ください。

ガターアイコンでKotlin/Nativeコードを実行

以前、Kotlin/Native コードの実行は、ターミナル内か、IntelliJ IDEA で Gradle タスクを実行してのみ行えました。 これからは、他の Kotlin コードと同様に、ガターアイコンを使って簡単に実行できるようになっています。

native-gutter-icon

C interopにおけるパフォーマンスの改善

Kotlin/Native のパフォーマンスを改善するため、C  interopライブラリのビルドを再構築しました。 (これらのライブラリは、Kotlin コードで C および Objective-C ライブラリの宣言を使用できるようにするアーティファクトです。) 変更は内部的に行われたものですが、パフォーマンスの改善とアーティファクトのサイズ削減を確認できます。新しいツーリングによって、interop ライブラリの速度は以前の4倍となり、アーティファクトのサイズが25%から30%縮小されています!

interop ライブラリの使用も加速化されており、Kotlin 1.4-M2 では、C  interopを使った Kotlin プロジェクトのコンパイル時間が短縮されています。

コンパイラキャッシングと Gradle Daemon 使用の安定化

1.3.70では、Kotlin/Native コンパイルのパフォーマンスを改善するために、プロジェクト依存関係のキャッシングGradle Daemon からのコンパイラの実行という2つの新機能を導入しました。 これらは取り組み中の機能であったため、ユーザーの中には、特定のケースにおいて課題や安定性不足を経験した人もいたかと思います。

皆さんからのフィードバックのお陰で、これらの機能に生じていた多数の課題を修正し、安定性を総合的に改善することができました。 これらの機能で問題に遭遇していたユーザーや Kotlin/Native の最新バージョンを試す機会がなかったユーザーは、ぜひ試してみてください。

Kotlin/JS の改善

1.4-M2 では、Kotlin の JavaScript ターゲットは、Gradle の命名規則を Kotlin ターゲットの命名規則にさらに近づけて調整しています。 また、コンパイラ設定により細かい制御を追加、@JsExport 注釈のcommonコード対応、webpack によるデフォルトでの CSS サポートを有効化しています。

Gradle DSL の変更

命名の変更

他の Kotlin ターゲットにさらに近づけるため、一部の一般的に使用されるKotlin/JS Gradle 構成の命名を変更しました。 Kotlin/JS Gradle プロジェクトにおけるこのデフォルトの構成ブロックを1.4-M2で見てみましょう。変更された2つの命名が示されています。

  • targetjs となっており、Kotlin マルチプラットフォームプラグインで使用される構文と一貫しています。
  • Kotlin 1.4-M1で導入された produceExecutable()binaries.executable() となっており、Kotlin/Native で使用されている命名と一貫しています。

binaries.executable() の詳細については、1.4-M1 に関するブログ記事の「Kotlin/JS | Gradle DSLの変更」のセクションを参照してください。

プロジェクト単位のコンパイラの設定

Kotlin 1.4-M1 において、最適化された DCE、TypeScript 宣言プレビューのほか、デフォルト、IR、そして両方のコンパイラモード間を切り替える gradle.properties の設定などが搭載された、新しい IR コンパイラバックエンドを初めて導入しました。 M2 では、使用されているコンパイラモードに対して、Gradle 構成から直接プロジェクト単位で行える細かい制御が導入されています。

コンパイラモード間の切り替えを行うには、Gradle ビルドスクリプトで、コンパイラのタイプを js 関数に渡します。 例:

このようにプロジェクトのコンパイラタイプを設定すると、gradle.properties に指定されたデフォルトの設定がオーバーライドされます。

Gradle からの webpack の css-loader サポート

Kotlin/JS Gradle プラグインは、ブラウザのアーティファクトを作成するために、デフォルトで webpack を使用します。カスタマイズできる設定がたくさんあります。 プロジェクトを構築するために使用されている webpack 構成ファイルを直接変更することで、すべてのオプションを変更することができますが、最もよく使用されている設定には、Gradle DSL から直接アクセスできるようにしました。

Kotlin 1.4-M2 では、ブラウザをターゲットとしたプロジェクトについては、webpack の css-loader がデフォルトで有効化されます。 つまり、プロジェクトと、スタイルシートを含む依存関係に CSS を追加すると、ほとんど場合、構成を行わずにすぐに使用できるようになっています。 以前、こういった状況では、Module parse failed: Unexpected character '@' (14:0) などのエラーが発生していました。

この CSS 統合の動作を調整するには、js.browser.webpackTask.cssSettings を使用してください。

cssSettings.enabled を使うと、プロジェクトが css-loader を使用すべきかどうかを変更できます(デフォルトでは有効化されています)。

cssSettings.mode を使うと、見つかった CSS をどのように処理するかを指定できます。 使用できるのは、次の値です。

  • "inline"(デフォルト): スタイルはグローバルの <style> タグに追加されます。
  • "extract": スタイルは、別のファイルに抽出されます。 その上で、HTML ページからインクルードされます。
  • "import": スタイルはストリングとして処理されます。 コードから CSS にアクセスする必要がある場合に便利です(例: val styles = require("main.css"))。

同じプロジェクトに別のモードを使用する場合は、cssSettings.rules を使用できます。 ここでは、KotlinWebpackCssRules のリストを指定でき、それぞれに、モードだけでなく、include と exclude パターンも定義することができます。 これらのパターンの詳細については、webpack ドキュメンテーションのincludeexclude のルールを参照してください。

カスタマイズ可能なモジュール名

JavaScript のモジュール名を Gradle ビルドスクリプトから直接変更できるようになりました。

これは、build/js/packages/myModuleName で生成されるモジュールの名前を変更し、対応する .js.d.ts のファイル名にも適用されます。 build/distributions の webpack 出力には影響しません。 webpack化されたファイルの名前を変更するには、js.browser.webpackTask.outputFileName を使用できます。

common コードにおける @JsExport 注釈

IR コンパイラバックエンドを使用している場合に、JavaScript または TypeScript から使用できる最上位の宣言を行うために使用できる @JsExport 注釈が、common コードで使用できるようになりました。 これにより、カスタム注釈やタイプエイリアスを使用する必要がなくなり、マルチプラットフォームの Kotlin プロジェクトから JavaScript ライブラリを構築できるという道が切り開かれます。

作業の効率性に関するその他の改善と注目すべき修正点

  • ブラウザと nodejs ターゲットの一般的な操作に使用される Gradle タスクは、個別のタスクグループにまとめられました。 kotlin browserkotlin node グループは、IntelliJ IDEA の Gradle ツールウィンドウに表示されるか、タスクをリスト表示する場合は ./gradlew tasks --all で表示することができます。
  • node.js ターゲットのテストを実行する場合、デバッガーはブレークポイントで正しく停止するようになりました。
  • コンパイルに both モードを使用するプロジェクトとライブラリにおいて、klib の依存関係が正しく解決されるようになりました。

互換性

一部のコーナーケースにおいて、Kotlin 1.4には1.3との下位互換性はありません。 Kotlin言語委員会はそういったケースを注意深くレビューし、「互換性ガイド」(これに似た様式)として掲載する予定です。 現時点では、YouTrackでこのリストをご覧ください。

プレリリースに関する注意事項

下位互換性保証は、プレリリースバージョンには適用されません。 機能や API は、後続のリリースで変更する場合があります。 最終RCに達すると、プレリリースバージョンで生成したすべてのバイナリは、コンパイラによって使用禁止となります。その場合、1.4-Mxでコンパイルしたすべてのものを再コンパイルする必要があります。

新機能を試すには

いつものように、play.kotl.inKotlinをオンラインで試すことができます。

IntelliJ IDEAAndroid Studio 内で、Kotlin プラグインをバージョン1.4-M2 に更新できます。 その方法についてはこれを参照してください。

プレリリースバージョンをインストールする前に作成された既存のプロジェクトを使用する場合、GradleまたはMavenでプレビューバージョン用にビルドを構成する必要があります。

コマンドラインコンパイラは、GitHubリリースページからダウンロードできます。

このリリースとともに公開された次のバージョンのライブラリを使用できます。

リリースの詳細と互換性のあるライブラリの一覧は、ここから入手できます。

ご意見をお寄せください

バグを見つけた場合は、ぜひ課題トラッカーにご報告ください。 すべての重要な課題については、次のKotlinリリースまで課題解決を延期することなく、最終リリース前に修正したいと思っています。

また、ぜひ Kotlin Slack\#eapチャンネル にご参加ください(招待状はこちらから入手できます)。 このチャンネルでは、質問、ディスカッションへの参加、新しいプレビュービルドについて知ることができます。

Kotlinを使ってみよう!

ご協力いただいた外部貢献者

このリリースに含められた Pull リクエストは、次の外部貢献者からいただきました。ご協力いただきありがとうございました。

[原文Original post in English is written by Ekaterina Volodko