コンピレーションの構成
Kotlinマルチプラットフォームプロジェクトは、アーティファクトを生成するためにコンピレーションを使用します。各ターゲットには、たとえば製品用とテスト用など、1つ以上のコンピレーションを含めることができます。
各ターゲットには、デフォルトのコンピレーションとして以下が含まれます。
- JVM、JS、およびNativeターゲットの
main
およびtest
コンピレーション。 - Androidターゲットの場合、Androidビルドバリアントごとのコンピレーション。
製品コードと単体テスト以外のものをコンパイルする必要がある場合、たとえば結合テストやパフォーマンステストの場合は、カスタムコンピレーションを作成できます。
アーティファクトがどのように生成されるかを以下で構成できます。
- プロジェクト内のすべてのコンピレーションを一括で構成する。
- 1つのターゲットが複数のコンピレーションを持つことができるため、1つのターゲットのコンピレーションを構成する。
- 特定のコンピレーションを構成する。
すべてのターゲットまたは特定のターゲットで利用可能なコンピレーションパラメータのリストとコンパイラオプションを参照してください。
すべてのコンピレーションを構成する
この例では、すべてのターゲットに共通するコンパイラオプションを構成します。
kotlin {
compilerOptions {
allWarningsAsErrors.set(true)
}
}
kotlin {
compilerOptions {
allWarningsAsErrors = true
}
}
1つのターゲットのコンピレーションを構成する
kotlin {
jvm {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_1_8)
}
}
}
kotlin {
jvm {
compilerOptions {
jvmTarget = JvmTarget.JVM_1_8
}
}
}
1つのコンピレーションを構成する
kotlin {
jvm {
val main by compilations.getting {
compileTaskProvider.configure {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_1_8)
}
}
}
}
}
kotlin {
jvm {
compilations.main {
compileTaskProvider.configure {
compilerOptions {
jvmTarget = JvmTarget.JVM_1_8
}
}
}
}
}
カスタムコンピレーションを作成する
製品コードと単体テスト以外のものをコンパイルする必要がある場合、たとえば結合テストやパフォーマンステストの場合は、カスタムコンピレーションを作成します。
カスタムコンピレーションの場合、すべての依存関係を手動で設定する必要があります。カスタムコンピレーションのデフォルトソースセットは、commonMain
およびcommonTest
ソースセットに依存しません。
たとえば、jvm
ターゲットの結合テスト用のカスタムコンピレーションを作成するには、integrationTest
コンピレーションとmain
コンピレーションの間にassociateWith
リレーションを設定します。
kotlin {
jvm {
compilations {
val main by getting
val integrationTest by creating {
// Import main and its classpath as dependencies and establish internal visibility
associateWith(main)
defaultSourceSet {
dependencies {
implementation(kotlin("test-junit"))
/* ... */
}
}
// Create a test task to run the tests produced by this compilation:
testRuns.create("integration") {
// Configure the test task
setExecutionSourceFrom(integrationTest)
}
}
}
}
}
kotlin {
jvm {
compilations.create('integrationTest') {
def main = compilations.main
// Import main and its classpath as dependencies and establish internal visibility
associateWith(main)
defaultSourceSet {
dependencies {
implementation kotlin('test-junit')
/* ... */
}
}
// Create a test task to run the tests produced by this compilation
testRuns.create('integration') {
// Configure the test task
setExecutionSourceFrom(compilations.integrationTest)
}
}
}
}
コンピレーションを関連付けることで、メインコンピレーションの出力を依存関係として追加し、コンピレーション間のinternal
可視性を確立します。
カスタムコンピレーションは他のケースでも必要です。たとえば、最終的なアーティファクトで異なるJVMバージョンのコンピレーションを結合したい場合や、すでにGradleでソースセットを設定していてマルチプラットフォームプロジェクトに移行したい場合などです。
androidTarget
のカスタムコンピレーションを作成するには、Android Gradleプラグインを通じてビルドバリアントを設定してください。
JVMのコンピレーション
マルチプラットフォームプロジェクトでjvm
ターゲットを宣言すると、Kotlin Multiplatformプラグインは自動的にJavaソースセットを作成し、それらをJVMターゲットのコンピレーションに含めます。
共通ソースセットにはJavaリソースを含めることができないため、それらをマルチプラットフォームプロジェクトの対応する子ディレクトリに配置する必要があります。たとえば:
現在、Kotlin MultiplatformプラグインはJavaプラグインによって構成される一部のタスクを置き換えます。
- JARタスク:標準の
jar
の代わりに、アーティファクト名に基づくターゲット固有のタスクを使用します。たとえば、jvm()
ターゲット宣言の場合はjvmJar
、jvm("desktop")
の場合はdesktopJar
です。 - テストタスク:標準の
test
の代わりに、アーティファクト名に基づくターゲット固有のタスクを使用します。たとえば、jvmTest
です。 - リソース処理:
*ProcessResources
タスクの代わりに、リソースは対応するコンピレーションタスクによって処理されます。
これらのタスクは、ターゲットが宣言されると自動的に作成されます。ただし、必要に応じてJARタスクを手動で定義し、構成することができます。
// Shared module's `build.gradle.kts` file
plugins {
kotlin("multiplatform") version "2.2.0"
}
kotlin {
// Specify the JVM target
jvm {
// Add the task for JAR generation
tasks.named<Jar>(artifactsTaskName).configure {
// Configure the task
}
}
sourceSets {
jvmMain {
dependencies {
// Add JVM-specific dependencies
}
}
}
}
// Shared module's `build.gradle` file
plugins {
id 'org.jetbrains.kotlin.multiplatform' version '2.2.0'
}
kotlin {
// Specify the JVM target
jvm {
// Add the task for JAR generation
tasks.named<Jar>(artifactsTaskName).configure {
// Configure the task
}
}
sourceSets {
jvmMain {
dependencies {
// Add JVM-specific dependencies
}
}
}
}
このターゲットはKotlin Multiplatformプラグインによって公開され、Javaプラグインに固有の手順は必要ありません。
ネイティブ言語との相互運用性を構成する
Kotlinはネイティブ言語との相互運用性を提供し、特定のコンピレーションのためにこれを構成するDSLを提供します。
ネイティブ言語 | サポートされているプラットフォーム | コメント |
---|---|---|
C | すべてのプラットフォーム | |
Objective-C | Appleプラットフォーム (macOS, iOS, watchOS, tvOS) | |
Swift via Objective-C | Appleプラットフォーム (macOS, iOS, watchOS, tvOS) | Kotlinは@objc 属性でマークされたSwift宣言のみを使用できます。 |
コンピレーションは複数のネイティブライブラリと対話できます。ビルドファイルの定義ファイルまたはcinterops
ブロックで利用可能なプロパティを使用して相互運用性を構成します。
kotlin {
linuxX64 { // Replace with a target you need.
compilations.getByName("main") {
val myInterop by cinterops.creating {
// Def-file describing the native API.
// The default path is src/nativeInterop/cinterop/<interop-name>.def
definitionFile.set(project.file("def-file.def"))
// Package to place the Kotlin API generated.
packageName("org.sample")
// Options to be passed to compiler by cinterop tool.
compilerOpts("-Ipath/to/headers")
// Directories to look for headers.
includeDirs.apply {
// Directories for header search (an equivalent of the -I<path> compiler option).
allHeaders("path1", "path2")
// Additional directories to search headers listed in the 'headerFilter' def-file option.
// -headerFilterAdditionalSearchPrefix command line option equivalent.
headerFilterOnly("path1", "path2")
}
// A shortcut for includeDirs.allHeaders.
includeDirs("include/directory", "another/directory")
}
val anotherInterop by cinterops.creating { /* ... */ }
}
}
}
kotlin {
linuxX64 { // Replace with a target you need.
compilations.main {
cinterops {
myInterop {
// Def-file describing the native API.
// The default path is src/nativeInterop/cinterop/<interop-name>.def
definitionFile = project.file("def-file.def")
// Package to place the Kotlin API generated.
packageName 'org.sample'
// Options to be passed to compiler by cinterop tool.
compilerOpts '-Ipath/to/headers'
// Directories for header search (an equivalent of the -I<path> compiler option).
includeDirs.allHeaders("path1", "path2")
// Additional directories to search headers listed in the 'headerFilter' def-file option.
// -headerFilterAdditionalSearchPrefix command line option equivalent.
includeDirs.headerFilterOnly("path1", "path2")
// A shortcut for includeDirs.allHeaders.
includeDirs("include/directory", "another/directory")
}
anotherInterop { /* ... */ }
}
}
}
}
Androidのコンピレーション
Androidターゲット用にデフォルトで作成されるコンピレーションは、Androidビルドバリアントに結び付けられています。各ビルドバリアントに対して、同じ名前のKotlinコンピレーションが作成されます。
次に、各バリアント用にコンパイルされる各Androidソースセットに対して、そのソースセット名にターゲット名がプレフィックスとして付けられたKotlinソースセットが作成されます。たとえば、Androidソースセットdebug
とandroidTarget
という名前のKotlinターゲットの場合、KotlinソースセットはandroidDebug
となります。これらのKotlinソースセットは、バリアントのコンピレーションに適切に追加されます。
デフォルトのソースセットcommonMain
は、各本番(アプリケーションまたはライブラリ)バリアントのコンピレーションに追加されます。commonTest
ソースセットも同様に、単体テストおよび計装テストバリアントのコンピレーションに追加されます。
kapt
によるアノテーション処理もサポートされていますが、現在の制限により、Androidターゲットがkapt
の依存関係が構成される前に作成されている必要があり、これはKotlinソースセットの依存関係内ではなく、トップレベルのdependencies {}
ブロックで行う必要があります。
kotlin {
androidTarget { /* ... */ }
}
dependencies {
kapt("com.my.annotation:processor:1.0.0")
}
ソースセット階層のコンピレーション
KotlinはdependsOn
関係を使用してソースセット階層を構築できます。
ソースセットjvmMain
がソースセットcommonMain
に依存している場合:
jvmMain
が特定のターゲット用にコンパイルされるたびに、commonMain
もそのコンピレーションに参加し、JVMクラスファイルなどの同じターゲットバイナリ形式にコンパイルされます。jvmMain
のソースは、commonMain
の宣言(内部宣言を含む)を「参照」し、commonMain
の依存関係(implementation
依存関係として指定されたものも含む)も参照します。jvmMain
は、commonMain
の期待される宣言に対してプラットフォーム固有の実装を含めることができます。commonMain
のリソースは常に処理され、jvmMain
のリソースとともにコピーされます。jvmMain
とcommonMain
の言語設定は一貫している必要があります。
言語設定は、次のような方法で一貫性がチェックされます。
jvmMain
は、commonMain
のlanguageVersion
以上であるlanguageVersion
を設定する必要があります。jvmMain
は、commonMain
が有効にしているすべての不安定な言語機能を有効にする必要があります(バグ修正機能にはそのような要件はありません)。jvmMain
は、commonMain
が使用するすべての実験的アノテーションを使用する必要があります。apiVersion
、バグ修正言語機能、およびprogressiveMode
は任意に設定できます。
GradleのIsolated Projects機能を構成する
この機能は実験的であり、現在Gradleではプレアルファ状態にあります。Gradle 8.10以降のバージョンでのみ、評価目的でご利用ください。この機能は、いつでも削除または変更される可能性があります。この機能に関するフィードバックをYouTrackでお待ちしております。オプトインが必要です(詳細は下記参照)。
GradleはIsolated Projects機能を提供しており、個々のプロジェクトを「分離」することでビルドパフォーマンスを向上させます。この機能は、プロジェクト間でビルドスクリプトとプラグインを分離し、並行して安全に実行できるようにします。
この機能を有効にするには、Gradleの指示に従ってシステムプロパティを設定してください。
Isolated Projects機能の詳細については、Gradleのドキュメントを参照してください。