Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to configure Kotlin jvmTarget in a Multiplatform Android module?

I'm getting this build error:

Cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option Adding support for Java 8 language features could solve this issue.

Trying to compile this build script for a multiplatform module in Android Studio:

import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget

plugins {
    kotlin("multiplatform")
    id("com.android.library")
}

repositories {
    mavenCentral()
}

kotlin {
    android()
    ios {
        binaries {
            framework {
                baseName = "bandit"
            }
        }
    }
    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.1.1")
                implementation("com.squareup.okio:okio-multiplatform:3.0.0-alpha.3")
                implementation("com.squareup.okio:okio-fakefilesystem-multiplatform:3.0.0-alpha.3")
            }
        }
        val commonTest by getting {
            dependencies {
                implementation(kotlin("test-common"))
                implementation(kotlin("test-annotations-common"))
            }
        }
        val androidMain by getting
        val androidTest by getting {
            dependencies {
                implementation(kotlin("test-junit"))
                implementation("junit:junit:4.13.2")
            }
        }
        val iosMain by getting
        val iosTest by getting

        all {
            languageSettings.apply {
                enableLanguageFeature("InlineClasses")
                useExperimentalAnnotation("kotlin.time.ExperimentalTime")
                useExperimentalAnnotation("okio.ExperimentalFileSystem")
            }
        }
    }
}

android {
    compileSdkVersion(30)
    defaultConfig {
        minSdkVersion(23)
        targetSdkVersion(30)
    }
    sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
}

val packForXcode by tasks.creating(Sync::class) {
    group = "build"
    val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
    val sdkName = System.getenv("SDK_NAME") ?: "iphonesimulator"
    val targetName = "ios" + if (sdkName.startsWith("iphoneos")) "Arm64" else "X64"
    val framework =
        kotlin.targets.getByName<KotlinNativeTarget>(targetName).binaries.getFramework(mode)
    inputs.property("mode", mode)
    dependsOn(framework.linkTask)
    val targetDir = File(buildDir, "xcode-frameworks")
    from({ framework.outputDirectory })
    into(targetDir)
}
tasks.getByName("build").dependsOn(packForXcode)

This is a pretty vanilla Multiplatform build script, mostly auto-generated by Jetbrain's Mobile plugin. I cannot solve this the usual way by inserting this at the bottom of the Android block:

    kotlinOptions {
        jvmTarget = "1.8"
    }

kotlinOptions is an unresolved reference here. Considering how generic this error is, I'm surprised how little there is on the internet addressing it. There are a few posts of same or similar jvmTarget errors, but they were all posted from build contexts different to this one. The only instance of somebody having exactly the same error is here:

kotlinOptions in kotlin multiplatform project

Strangely enough, the original poster allegedly managed to solve the problem just by tinkering with his androidx imports. It is perhaps worth noting that all six of my "Cannot inline bytecode" are associated with method calls to the new multiplatform Okio library. But it's surely more likely there's an error with my own setup rather than something the Jake-Wharton-gang have done.

like image 546
J. O. A. Rayner-Hilles Avatar asked Apr 08 '21 17:04

J. O. A. Rayner-Hilles


People also ask

How do I add dependency to Kotlin?

Adding Android dependencies The workflow for adding Android-specific dependencies to a Kotlin Multiplatform module is the same as it is for pure Android projects: declare the dependency in your Gradle file and import the project. After that, you can use this dependency in your Kotlin code.

How do I add dependency to kotlin gradle?

You can connect one multiplatform project to another as a dependency. To do this, simply add a project dependency to the source set that needs it. If you want to use a dependency in all source sets, add it to the common one. In this case, other source sets will get their versions automatically.

How do you make a Kotlin multiplatform project?

Create the project from a templateIn Android Studio, select File | New | New Project. Select Kotlin Multiplatform App in the list of project templates, and click Next. Specify a name for your first application, and click Next. In the iOS framework distribution list, select Regular framework.

What is Kotlin multiplatform and how to use it?

Kotlin Multiplatform allows you to write common code that can be shared between Android and iOS. Sharing code between mobile platforms is one of the major Kotlin Multiplatform use cases. It is now possible to build mobile applications with parts of the code, such as business logic, connectivity, and more, shared between Android and iOS.

How are Kotlin source sets created for Android apps?

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 android. These Kotlin source sets are added to the variants’ compilations accordingly.

Can you have multiple targets in a multiplatform library?

You can have several targets for one platform in a multiplatform library. For example, these targets can provide the same API but use different libraries during runtime, such as testing frameworks and logging solutions. Dependencies on such a multiplatform library may fail to resolve because it isn’t clear which target to choose.

What is @Kotlin interoperability?

Kotlin provides interoperability with native languages and DSL to configure this for a specific compilation. Kotlin can use only Swift declarations marked with the @objc attribute. A compilation can interact with several native libraries. Configure interoperability in the cinterops block of the compilation with available parameters.


1 Answers

As per the documentation: https://kotlinlang.org/docs/mpp-dsl-reference.html#compilation-parameters

Don't be fooled by the Gradle docs' code examples into thinking a lot of this compilation syntax applies only to the Java block. This is how you specify the jvm version target for an Android build:

kotlin {
    android {
        compilations.all {
            kotlinOptions.jvmTarget = "1.8"
        }
    }
    ios {
        ...
like image 87
J. O. A. Rayner-Hilles Avatar answered Sep 17 '22 23:09

J. O. A. Rayner-Hilles