In the IDE I get these red-lines/errors. Hsowever,...
# multiplatform
s
In the IDE I get these red-lines/errors. Hsowever, it all builds and compiles without issue. My IDE is Android Studio 4.0.1, Kotlin 1.4.10, KMM Plugin 0.1.1 and 0.1.2 (tried both). I tried re-syncing gradle, re-build from scratch, invalidate caches & restart; all to no avial. Does anyone else see the same issue?
k
yes I noticed something similar today
but not all projects, just one
z
What about your
gradle.properties
settings?
k
kotlin.code.style=official
s
Copy code
org.gradle.jvmargs=-Xmx1536m
android.enableJetifier=true
kotlin.code.style=official

xcodeproj=./iosApp
#kotlin.mpp.enableGranularSourceSetsMetadata=true
#kotlin.native.enableDependencyPropagation=false
k
basically every source file in my
iosMain
has the same problem
s
@Kris Wong Same here. Not all of them… and yesterday it all looked good… Maybe the 0.1.2 version of the KMM plugin…? What I noticed is that the
External Libraries
section of the ‘Project’ browser looks different. I can find the the ‘Foundation’ library, but it looks quite different in the IDE now…
@Kris Wong Re-enabling (I disabled them earlier because of other issues) gets rid of the IDE’s red-lines.
Copy code
kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.native.enableDependencyPropagation=false
k
nice, for me those caused a build error in one of my projects
s
Same here. I had to disable these properties to get rid of this build-error….
Copy code
5:49 PM	Incompatible Kotlin/Native libraries
				There are 2 third-party libraries attached to the project that were compiled with an older Kotlin/Native compiler and cant be read in IDE:
				Gradle: com.russhwolf:multiplatform-settings-metadata:apple64Main:0.6.2
				Gradle: com.russhwolf:multiplatform-settings-metadata:appleMain:0.6.2
				Please edit Gradle buildfile(s) and specify library a version compatible with Kotlin/Native 1.4.10. Then re-import the project in IDE.
But that build-error no longer appears with these properties re-enabled… odd…
z
Hmm these settings are causing build error for me too 🤔
What gradle wrapper version you are using?
k
6.4 mostly
s
I was mistaken… I still get IDE errors (no build/compile errors), but in other spots (e.g.
import kolinx.coroutines.xxxxxx
are red now)
I use 6.5
k
i suspect this problem, for me, is due to the fact that I have the 1.4 Kotlin plugin, and the project is using 1.3.72
it probably can't parse the klibs
s
Copy code
kotlin.native.enableDependencyPropagation=false
This one enabled: I get
import kolinx.coroutines.xxxxxx
red-lines in the IDE. This one disabled: I get
import platform.xxxxx
red-lines in the IDE.
z
Ah yes, in such case that’s definitely the problem. You can fix it easily by installing an old plugin though
k
i've updated one of my projects, so can't do that. what I really need is 2 installations of the IDE. one with the old plugin and one with the new
it's disappointing that that's necessary
s
Is the Gradle version 6.5 the problem?
I’m using Kotlin 1.4.10, Coroutines 1.3.9-native-mt, Gradle wrapper 6.5, Android Studio 4.0.1, KMM Plugin 0.1.2
z
Hmm should be fine, have you tried on latest canary version of AS?
s
No… i’m trying this on a stable version of Android Studio….
k
stable versions have enough problems. i wouldn't touch canary 😂
s
The red-lines come and go…. even without changing these properties in gradle.properties…. confusing. E.g. I enabled
Copy code
kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.native.enableDependencyPropagation=false
and did a sync-with-gradle. Most red-lines went away, except for one:`import okio.toByteString`. All the
import platform…
are now fine… Then a ‘Rebuild Project’ and the
import kotlinx.coroutines.suspendCanncellableCoroutine
went red as well….
z
From my experience this kind of issue is happening quite often and it’s hard to find what’s the problem. I remember we had this issue once as for defining ios target we used
Copy code
ios()
but when we changed it to something like:
Copy code
val iOSTarget: (String, KotlinNativeTarget.() -> Unit) -> KotlinNativeTarget =
            if (System.getenv("SDK_NAME")?.startsWith("iphoneos") == true)
                ::iosArm64
            else
                ::iosX64

iOSTarget("ios") {...}
The issue got solved
s
Hmmmmmm…. we removed this in favor of the simpler
ios()
when moving to use the KMM plugin and it all looked good until today. Let me use that pattern again and see if it solves stuff. Thanks!
z
Yeah i did the same when I moved to 1.4 and the issue with red lines got back… 😕
s
Alas, your pattern give a build-error:
KotlinTarget with name 'iosX64' not found.
z
Oh I haven’t test this code on 1.4.10 yet, I used it with 1.3.72 before
r
You are definitely more likely to run into this sort of error when using
ios()
because it's setting up an intermediate source-set. Those gradle properties should help but it's still often spotty for me. Try in IDEA for comparison, and maybe try beta/canary Android Studio since newer AS is based off of newer IDEA. Also make sure your Kotlin IDE plugin matches the Kotlin language version you're using.
☝️ 1
z
@streetsofboston Can you try something like in this project: https://github.com/joreilly/BikeShare/blob/master/common/build.gradle.kts
s
Thanks @russhwolf I use 1.4.10 for both the Kotlin Plugin and the kotlin-version in my builds. With both these properties enabled, the IDE red-lines/errors I get a related to coroutines (I use 1.3.9.-native-mt) and okio. I don’t see issues regarding the ios ‘platform’ and such with anymore these enabled. These red-lines are only in the iosMain kotlin-files. The commonMain and androidMain look fine.
@zalewski.se Looking at the BikeShare, using
Copy code
val isiOSDevice = sdkName.orEmpty().startsWith("iphoneos")
        if (isiOSDevice) {
            iosArm64("iOS64")
        } else {
            iosX64("iOS")
        }
will give me that build-error
KotlinTarget with name 'iosX64' not found.
r
That's a really weird error to get if
ios()
is working since it uses that target internally
s
I get that error while synching-with-gradle.
z
Oh I’m not sure why it could happen 💦 I assume you don’t change targets manually for your compilation. Could it be an order problem in gradle file?
s
@zalewski.se I don’t change them manually. I created my KMM project using the wizard in Android Studio. When I replace the
ios()
with the
if (isIosDevice) ….
, i get that error.
I guess because it is still alpha, these things are to be ‘expected’ 🙂
z
@streetsofboston Could you share here your build.gradle file?
s
Copy code
import org.gradle.api.tasks.testing.logging.TestLogEvent
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    kotlin("multiplatform")
    kotlin("native.cocoapods")

    id("com.android.library")
    id("kotlin-android-extensions")

    id("com.apollographql.apollo")
    id("kotlinx-serialization")
}
group = "com.mycompany"
version = "1.0-SNAPSHOT"

repositories {
    gradlePluginPortal()
    google()
    jcenter()
    mavenCentral()
}
kotlin {
    android()
    ios()

    sourceSets {
        all {
            val isTestSource = name.contains("Test")

            languageSettings.apply {
                useExperimentalAnnotation("kotlin.RequiresOptIn")
                useExperimentalAnnotation("kotlinx.coroutines.ExperimentalCoroutinesApi")

                if (isTestSource) {
                    useExperimentalAnnotation("com.accenture.fetch.VisibleForTestingOnly")
                }
            }
        }

        val commonMain by getting {
            dependencies {
                implementation(Deps.Coroutines.core)
                implementation(Deps.stately)
                implementation(Deps.statelyConcurrency)
                implementation(Deps.multiplatformSettings)
                implementation(Deps.koinCore)
                implementation(Deps.Apollo.api)
                implementation(Deps.coreSerialization)
                api(Deps.kermit)
            }
        }
        val commonTest by getting {
            dependencies {
                implementation(Deps.KotlinTest.common)
                implementation(Deps.KotlinTest.annotations)

                implementation(Deps.multiplatformSettingsTest)
                implementation(Deps.koinTest)
            }
        }
        val androidMain by getting {
            dependencies {
                implementation(Deps.app_compat_x)
                implementation(Deps.Coroutines.android)
                implementation(Deps.Apollo.api)
                implementation(Deps.Apollo.runtime)
                implementation(Deps.Apollo.okHttpLoggingInterceptor)
            }
        }
        val androidTest by getting {
            dependencies {
                implementation(Deps.junit)
                implementation(Deps.KotlinTest.jvm)
                implementation(Deps.KotlinTest.junit)

                implementation(Deps.AndroidXTest.core)
                implementation(Deps.AndroidXTest.junit)
                implementation(Deps.AndroidXTest.runner)
                implementation(Deps.AndroidXTest.rules)
                implementation(Deps.Coroutines.test)
                implementation(Deps.mockk)
                implementation("org.robolectric:robolectric:4.3")

            }
        }
        val iosMain by getting {
            dependencies {
                implementation(Deps.Coroutines.core) {
                    version { strictly(Versions.coroutines) }
                }
                implementation(Deps.Apollo.api)
            }
        }
        val iosTest by getting
    }

    cocoapods {
        summary = "Common library for the KaMP starter kit"
        homepage = "<https://github.com/touchlab/KaMPStarter>"

        ios.deploymentTarget = "9.0"

        podfile = project.file("../iosApp/Podfile")
    }
}

android {
    compileSdkVersion(Versions.compile_sdk)
    sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
    defaultConfig {
        minSdkVersion(Versions.min_sdk)
        targetSdkVersion(Versions.target_sdk)
        versionCode = 1
        versionName = "1.0"
    }
    buildTypes {
        getByName("release") {
            isMinifyEnabled = false
        }
    }
    compileOptions {
        sourceCompatibility = Versions.java
        targetCompatibility = Versions.java
    }
}
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).apply {
        export(Deps.kermit)
        transitiveExport = true
    }

    inputs.property("mode", mode)
    dependsOn(framework.linkTask)
    val targetDir = File(buildDir, "xcode-frameworks")
    from({ framework.outputDirectory })
    into(targetDir)
}
tasks.getByName("build").dependsOn(packForXcode)

tasks.withType<KotlinCompile>().configureEach {
    kotlinOptions.jvmTarget = Versions.java.toString()
}

apollo {
    generateKotlinModels.set(true)
}

tasks.withType<Test> {
    testLogging {
        events(TestLogEvent.FAILED, TestLogEvent.STANDARD_OUT, TestLogEvent.STANDARD_ERROR)
    }
}
z
Could it be that packForXcode task is failing for you?
Can you comment it out for now and check again?
s
That was part generated by the wizard… It packs and links the ‘shared’ code as a framework for the ios project…. it should not matter for the IDE.
r
I've occasionally had problems go away by reordering the android and kmp plugins. What if you do
id("com.android.library")
first in your
plugins
block?
s
Commenting out the packForXcode does not fix it.
z
I meant to comment it and check if you still gonna get “KotinTarget with name ‘iosX64’ not found”. I don’t expect it to be the cause of IDE problem
s
@russhwolf Re-ordering the plugins (put com.android.library first) did not fix it…
@zalewski.se Removing the packForXCode solves the ‘iosX64’ not found. Thanks… but I would still need this to properly build 🙂 But it is a hint of what may be wrong .
It look like `
Copy code
kotlin.targets.getByName<KotlinNativeTarget>(targetName)
is the culprit when using the
if (isiOSDevice) … …
snippet 🙂
r
Oh yeah make sure that matches the target name you pass to
ios()
or
iosArm64()
or
iosX64()
z
Well let’s leave packForXcode task for later though, can you check now if the IDE error is still there?
s
The name seems to match… maybe an gradle configuration ordering issue?
The IDE error is gone with the
if (isiOSDevice)… …
snippet.
z
Nice! So now just to fix the packForXcode task ;) I’m a little bit tired as it’s 2am for me already, I can try to help tomorrow if you can’t make it till then
s
@zalewski.se Have a good night and thank you so much for your help. I’ll be ‘fixing’ the packForXcode task in lieu of the missing simple
ios()
instruction. 🙂
t
with HMPP enabled stuff is just a broken mess in the IDE. but recently I came across this code that Jetbrains uses internally to (I think) fix the problems in the IDE: https://github.com/Kotlin/kotlinx.coroutines/blob/1696809ac66753da6f6af71372a3bc4d634f7032/kotlinx-coroutines-core/build.gradle#L110 haven’t tried it myself yet
r
I would have thought you could do
kotlin.targets.getByName<KotlinNativeTarget>("ios").binaries.getFramework(mode)
and not need the
framework()
fun
💯 1
s
The call to
kotlin.targets.getByName<KotlinNativeTarget>(targetName)
throws an error that the target name is not found (the only target is available is
ios
, without the architecture-postfix when using the
if (onPhone) … …
code, and you’ll have to examine the `konanTarget`….).
Ah… Maybe the filtering on the konan-target and such is done by the
getFramework(mode)
on the `binaries`…. let me check… Checked: Yup!
r
When you do
getByName<KotlinNativeTarget>("ios")
it's looking for the target that you named "ios", which you're doing in both branches of
Copy code
if (onPhone) {
        iosArm64("ios")
    } else {
        iosX64("ios")
    }
s
Well, I fixed it for the red-lines in the
iosMain
source-set, but now I get red-lines in the `commonMain`….. Ugh!
Disabling setting the kotlin.native.enableDependencyPropagation=false fixes that….. 😕