配置编译项
Kotlin multiplatform projects use compilations for producing artifacts. Each target can have one or more compilations, for example, for production and test purposes.
For each target, default compilations include:
main
andtest
compilations for JVM, JS, and Native targets.- A compilation per Android build variant, for Android targets.
If you need to compile something other than production code and unit tests, for example, integration or performance tests, you can create a custom compilation.
You can configure how artifacts are produced in:
See the list of compilation parameters and compiler options available for all or specific targets.
配置所有编译项
This example configures a compiler option that is common across all targets:
【Kotlin】
kotlin {
compilerOptions {
allWarningsAsErrors.set(true)
}
}
【Groovy】
kotlin {
compilerOptions {
allWarningsAsErrors = true
}
}
为一个目标配置编译项
【Kotlin】
kotlin {
jvm {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_1_8)
}
}
}
【Groovy】
kotlin {
jvm {
compilerOptions {
jvmTarget = JvmTarget.JVM_1_8
}
}
}
配置一个编译项
【Kotlin】
kotlin {
jvm {
val main by compilations.getting {
compileTaskProvider.configure {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_1_8)
}
}
}
}
}
【Groovy】
kotlin {
jvm {
compilations.main {
compileTaskProvider.configure {
compilerOptions {
jvmTarget = JvmTarget.JVM_1_8
}
}
}
}
}
创建自定义编译项
If you need to compile something other than production code and unit tests, for example, integration or performance tests, create a custom compilation.
For example, to create a custom compilation for integration tests of the jvm()
target, add a new item to the compilations
collection.
For custom compilations, you need to set up all dependencies manually. The default source set of a custom compilation does not depend on the
commonMain
and thecommonTest
source sets.{style="note"}
【Kotlin】
kotlin {
jvm() {
compilations {
val main by getting
val integrationTest by compilations.creating {
defaultSourceSet {
dependencies {
// Compile against the main compilation's compile classpath and outputs:
implementation(main.compileDependencyFiles + main.output.classesDirs)
implementation(kotlin("test-junit"))
/* ... */
}
}
// Create a test task to run the tests produced by this compilation:
tasks.register("integrationTest") {
// Run the tests with the classpath containing the compile dependencies (including 'main'),
// runtime dependencies, and the outputs of this compilation:
classpath = compileDependencyFiles + runtimeDependencyFiles + output.allOutputs
// Run only the tests from this compilation's outputs:
testClassesDirs = output.classesDirs
}
}
}
}
}
【Groovy】
kotlin {
jvm() {
compilations.create('integrationTest') {
defaultSourceSet {
dependencies {
def main = compilations.main
// Compile against the main compilation's compile classpath and outputs:
implementation(main.compileDependencyFiles + main.output.classesDirs)
implementation kotlin('test-junit')
/* ... */
}
}
// Create a test task to run the tests produced by this compilation:
tasks.register('jvmIntegrationTest', Test) {
// Run the tests with the classpath containing the compile dependencies (including 'main'),
// runtime dependencies, and the outputs of this compilation:
classpath = compileDependencyFiles + runtimeDependencyFiles + output.allOutputs
// Run only the tests from this compilation's outputs:
testClassesDirs = output.classesDirs
}
}
}
}
You also need to create a custom compilation in other cases, for example, if you want to combine compilations for different JVM versions in your final artifact, or you have already set up source sets in Gradle and want to migrate to a multiplatform project.
Compilation for JVM
When you declare the jvm
target in your multiplatform project, the Kotlin Multiplatform plugin automatically
creates Java sources sets and includes them in the compilations of the JVM target.
The common source sets can't include Java resources, so you should place them in the corresponding child directories of your multiplatform project. For example:
Currently, the Kotlin Multiplatform plugin replaces some tasks configured by the Java plugin:
- JAR task: instead of a standard
jar
, it uses a target-specific task based on the artifact's name, for example,jvmJar
for thejvm()
target declaration anddesktopJar
forjvm("desktop")
. - Test task: instead of a standard
test
, it uses a target-specific task based on the artifact's name, for example,jvmTest
. - Resource processing: instead of
*ProcessResources
tasks, resources are handled by the corresponding compilation tasks.
These tasks are created automatically when the target is declared. However, you can manually define the JAR task and configure it if necessary:
【Kotlin】
// Shared module's `build.gradle.kts` file
plugins {
kotlin("multiplatform") version "2.1.20"
}
kotlin {
// Specify the JVM target
jvm {
// Add the task for JAR generation
tasks.named(artifactsTaskName).configure {
// Configure the task
}
}
sourceSets {
jvmMain {
dependencies {
// Add JVM-specific dependencies
}
}
}
}
【Groovy】
// Shared module's `build.gradle` file
plugins {
id 'org.jetbrains.kotlin.multiplatform' version '2.1.20'
}
kotlin {
// Specify the JVM target
jvm {
// Add the task for JAR generation
tasks.named(artifactsTaskName).configure {
// Configure the task
}
}
sourceSets {
jvmMain {
dependencies {
// Add JVM-specific dependencies
}
}
}
}
This target is published by the Kotlin Multiplatform plugin and doesn't require steps that are specific to the Java plugin.
配置与原生语言的互操作
Kotlin provides interoperability with native languages and DSL to configure this for a specific compilation.
Native language | Supported platforms | Comments |
---|---|---|
C | All platforms, except for WebAssembly | |
Objective-C | Apple platforms (macOS, iOS, watchOS, tvOS) | |
Swift via Objective-C | Apple platforms (macOS, iOS, watchOS, tvOS) | Kotlin can use only Swift declarations marked with the @objc attribute. |
A compilation can interact with several native libraries. Configure interoperability with available properties in the
definition file or in the cinterops
block of
your build file:
【Kotlin】
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/.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 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 { /* ... */ }
}
}
}
【Groovy】
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/.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 eqivalent of the -I 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 编译项
The compilations created for an Android target by default are tied to Android build variants: for each build variant, a Kotlin compilation is created under the same name.
Then, for each Android source set compiled for
each of the variants, a Kotlin source set is created under that source set name prepended by the target name, like the
Kotlin source set androidDebug
for an Android source set debug
and the Kotlin target named androidTarget
.
These Kotlin source sets are added to the variants' compilations accordingly.
The default source set commonMain
is added to each production (application or library) variant's compilation.
The commonTest
source set is similarly added to the compilations of unit test and instrumented test variants.
Annotation processing with kapt
is also supported, but due to current limitations it requires that the Android target
is created before the kapt
dependencies are configured, which needs to be done in a top-level dependencies {}
block rather
than within Kotlin source set dependencies.
kotlin {
androidTarget { /* ... */ }
}
dependencies {
kapt("com.my.annotation:processor:1.0.0")
}
源代码集分层结构的编译项
Kotlin can build a source set hierarchy with the dependsOn
relation.
If the source set jvmMain
depends on a source set commonMain
then:
- Whenever
jvmMain
is compiled for a certain target,commonMain
takes part in that compilation as well and is also compiled into the same target binary form, such as JVM class files. - Sources of
jvmMain
'see' the declarations ofcommonMain
, including internal declarations, and also see the dependencies ofcommonMain
, even those specified asimplementation
dependencies. jvmMain
can contain platform-specific implementations for the expected declarations ofcommonMain
.- The resources of
commonMain
are always processed and copied along with the resources ofjvmMain
. - The language settings of
jvmMain
andcommonMain
should be consistent.
Language settings are checked for consistency in the following ways:
jvmMain
should set alanguageVersion
that is greater than or equal to that ofcommonMain
.jvmMain
should enable all unstable language features thatcommonMain
enables (there's no such requirement for bugfix features).jvmMain
should use all experimental annotations thatcommonMain
uses.apiVersion
, bugfix language features, andprogressiveMode
can be set arbitrarily.
Configure Isolated Projects feature in Gradle
This feature is Experimental and is currently in a pre-alpha state with Gradle. Use it only with Gradle versions 8.10 or higher, and solely for evaluation purposes. The feature may be dropped or changed at any time. We would appreciate your feedback on it in YouTrack. Opt-in is required (see details below).
{style="warning"}
Gradle provides the Isolated Projects feature, which improves build performance by "isolating" individual projects from each other. The feature separates the build scripts and plugins between projects, allowing them to run safely in parallel.
To enable this feature, follow Gradle's instructions to set the system property.
For more information about the Isolated Projects feature, see Gradle's documentation.