davidepianca98 / KMQTT

Kotlin Multiplatform MQTT client & embeddable and standalone broker
MIT License
188 stars 29 forks source link

Kotlin native could not find "openssl" #14

Closed FJerabek closed 1 year ago

FJerabek commented 2 years ago

I am trying to create project using this library with kotlin native on linux 64bit, but i am getting strange error about missing openssl. I have installed openssl and libssl-dev but the error still persists.

e: Could not find "openssl" in [/home/fjerabek/mqttTest, /home/fjerabek/.konan/klib, /home/fjerabek/.konan/kotlin-native-prebuilt-linux-x86_64-1.7.0/klib/common, /home/fjerabek/.konan/kotlin-native-prebuilt-linux-x86_64-1.7.0/klib/platform/linux_x64]

Execution failed for task ':compileKotlinNative'.
> Compilation finished with errors

Am i missing some other library on my system ?

davidepianca98 commented 2 years ago

Hello, how did you include the dependency in gradle? Also it looks like you are using Kotlin 1.7.0, I have yet to try to compile with that version but I will check soon.

FJerabek commented 2 years ago

I am including the dependency by adding this to the build.gradle.kts file into the sourceSets block.

commonMain {
    dependencies {
        implementation("com.github.davidepianca98.KMQTT:kmqtt:0.3.2")
    }
}

The resulting build file looks like this. It is the default template that jetbrains is using for kotlin native projects only with the added dependency.

plugins {
    kotlin("multiplatform") version "1.7.0"
}

group = "org.example"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
    maven(url = "https://jitpack.io")
}

kotlin {
    val hostOs = System.getProperty("os.name")
    val isMingwX64 = hostOs.startsWith("Windows")
    val nativeTarget = when {
        hostOs == "Mac OS X" -> macosX64("native")
        hostOs == "Linux" -> linuxX64("native")
        isMingwX64 -> mingwX64("native")
        else -> throw GradleException("Host OS is not supported in Kotlin/Native.")
    }

    nativeTarget.apply {
        binaries {
            executable {
                entryPoint = "main"
            }
        }
    }
    sourceSets {
        commonMain {
            dependencies {
                implementation("com.github.davidepianca98.KMQTT:kmqtt:0.3.2")
            }
        }
        val nativeMain by getting
        val nativeTest by getting
    }
}

For now i am trying out the library in jvm and kotlin 1.7.0 and it working great so far, but cannot get it to work with native.

davidepianca98 commented 2 years ago

Unfortunately Kotlin Native doesn't provide OpenSSL bindings so I usually compile my version using a script. Apparently this doesn't get included in the library files you get from Jitpack. If you want you can download the prebuilt version from here https://github.com/davidepianca98/KMQTT/blob/master/src/nativeInterop/openssl-linux-x64.klib and include it with the following code changing the directory.

val linuxArm64Main by getting {
    dependencies {
        implementation(files("src/nativeInterop/openssl-linux-x64.klib"))
    }
}

If, for whatever reason, you do not trust the prebuilt library you can build it yourself with Docker and the files in this directory: https://github.com/davidepianca98/KMQTT/tree/master/src/linuxX64Main/resources.

I will be looking for an easier way to do this, but for now this is it unfortunately.

FJerabek commented 2 years ago

I must be missing something :thinking:. I added the dependency to the openssl library and looks like it loaded correctly because i can use openssl library methods, but now the problem is not in compileKotlinNative task but in linkDebugExecutableNative.

e: Could not find "openssl" in [/home/fjerabek/mqttTest, /home/fjerabek/.konan/klib, /home/fjerabek/.konan/kotlin-native-prebuilt-linux-x86_64-1.7.0/klib/common, /home/fjerabek/.konan/kotlin-native-prebuilt-linux-x86_64-1.7.0/klib/platform/linux_x64]

Execution failed for task ':linkDebugExecutableNative'.
> Compilation finished with errors

When i add the klib file to one of those locations and change the name to openssl.klib gradle complains about caching

/home/fjerabek/.gradle/caches/modules-2/files-2.1/com.github.davidepianca98.KMQTT/kmqtt-linuxx64/0.3.2/704c50f7b3bf5fd394f044a485dbba73cdc81f59/kmqtt-linuxx64-0.3.2 is going to be cached, but its dependency isn't: /home/fjerabek/mqttTest/openssl
davidepianca98 commented 2 years ago

I tried creating a brand new Kotlin Native project, then i added openssl-linux-x64.klib in the src directory and modified the build gradle file in the following way (I commented the choice of the platform because I am on Windows and I wanted to build for Linux).

plugins {
    kotlin("multiplatform") version "1.7.0"
}

group = "me.x"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
    maven(url = "https://jitpack.io")
}

kotlin {
    val hostOs = System.getProperty("os.name")
    val isMingwX64 = hostOs.startsWith("Windows")
    //val nativeTarget = when {
    //    hostOs == "Mac OS X" -> macosX64("native")
    //    hostOs == "Linux" -> linuxX64("native")
    //    isMingwX64 -> mingwX64("native")
    //    else -> throw GradleException("Host OS is not supported in Kotlin/Native.")
    //}
    val nativeTarget = linuxX64("native")

    nativeTarget.apply {
        binaries {
            executable {
                entryPoint = "main"
            }
        }
    }
    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation("com.github.davidepianca98.KMQTT:kmqtt:0.3.2")
            }
        }
        val nativeMain by getting {
            dependencies {
                implementation(files("src/openssl-linux-x64.klib"))
            }
        }
        val nativeTest by getting
    }
}

Then I made this main file:

import mqtt.broker.Broker

fun main() {
    Broker().listen()
}

And finally I ran linkDebugExecutableNative and it's compiling correctly the binary file and it's running correctly. Please try to check for differences and let me know if changing your setup makes it work.

FJerabek commented 2 years ago

This is weird. The same build script works on windows (I tried it on my windows machine) but not on linux. I tried cleaning the build cache and still no difference. The gradle versions are the same. I also tried it inside wsl to try other "linux" system and i cannot get it build in wsl too.

davidepianca98 commented 2 years ago

You are right, I have no idea what's going on, because linkReleaseExecutableNative works but linkDebugExecutableNative doesn't. I will continue to try to find the issue but it could be something wrong with the Kotlin build system.

davidepianca98 commented 1 year ago

Solved in 0.3.3