How to add a dependency in a multiplatform kotlin / native intellij project? - gradle

I have the following build.gradle configuration:
plugins {
id 'org.jetbrains.kotlin.multiplatform' version '1.3.41'
}
repositories {
mavenCentral()
}
kotlin {
linuxX64("linux") {
binaries {
executable {
entryPoint = 'sample.main'
runTask?.args('')
}
}
}
sourceSets {
linuxMain {
dependencies {
api("org.http4k:http4k-core:3.183.0")
}
}
linuxTest {
}
}
}
And the following source file src/linuxMain/kotlin/sample/SampleLinux.kt :
package sample
fun hello(): String = "Hello, Kotlin/Native!"
fun main() {
println(hello())
}
How to add a external library in order to be able to use autocomplete in imports for the library org.http4k:http4k-core:3.183.0?
As you can see, I tried to add the line api("org.http4k:http4k-core:3.183.0") in linuxMain dependencies, but although intellij show the library in External Libraries section, I cannot work with the packages neither classes of http4k in SampleLinux.kt file: any org.http4k..... import attempt is not recognized and generates compilation error.

After a quick look, I am almost sure that http4k is JVM-only library, at least for now. According to this issue, they are still waiting for Native to grow. If you are interested, it would be nice if one can ask the library maintainers again. As far as K/N has grown a lot by the last year, maybe they change their mind.

Related

How to import code from outside into gradle build file?

My build files are large and messy, making them difficult to read. like below:
plugins {
...
id "com.google.protobuf" version "0.8.17"
}
dependencies {
implementation "androidx.datastore:datastore-core:1.0.0"
implementation "com.google.protobuf:protobuf-javalite:3.18.0"
...
}
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.14.0"
}
// Generates the java Protobuf-lite code for the Protobufs in this project. See
// https://github.com/google/protobuf-gradle-plugin#customizing-protobuf-compilation
// for more information.
generateProtoTasks {
all().each { task ->
task.builtins {
java {
option 'lite'
}
}
}
}
}
I want to define the above code into an external file, and then introduce it into the build file, how should I do it?
According to the Gradle documentation, as of now it is not possible to move the plugin block to other file than the project’s build script or settings.gradle file.
For the other sections, let's say dependencies or protobuf, then you can move these sections on a separate gradle files and import them by using the following statement:
apply from: "${project.rootDir}/your-gradle-file"
Of course the path of your-gradle-file should be adjusted according to the project's folder structure you decide.
If you want to split the dependencies into multiple gradle file you can do the following:
on your main gradle file:
dependencies {
apply from: "${project.rootDir}/depsGroup1.gradle"
apply from: "${project.rootDir}/depsGroup2.gradle"
}
and within each depsGroup file:
dependencies {
implementation xyz
}

Gradle - Protobuf module is rebuilt almost every time

I have a Gradle build with a module generating grpc code. The gradle.build.kts uses version 0.9.1 of the protobuf plugin and the file looks like this:
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:$protobufVersion"
}
plugins {
id("grpc") {
artifact = "io.grpc:protoc-gen-grpc-java:$grpcVersion"
}
id("grpckt") {
artifact = "io.grpc:protoc-gen-grpc-kotlin:$grpcKotlinVersion:jdk8#jar"
}
}
generateProtoTasks {
ofSourceSet("main").forEach { task ->
task.plugins {
id("grpc")
id("grpckt")
}
task.builtins {
id("kotlin")
}
}
}
}
The code generation works well enough, but there is something causing Gradle to re-build that module even though nothing has changed causing the build to be a lot slower then it has to. Running the build with --scan I found this:
The task was not up-to-date because of the following reasons:
Output property 'destDir' file xxx/build/extracted-protos/main has been removed.
Seems like the build is "fighting" over that folder. Is there something wrong with my build configuration?

no build output compiled for common module of Kotlin Multiplatform project

I'm trying to figure out why dependent projects for my Kotlin MPP library don't see any provided modules in their common modules even though the targets (jvm, android) can see them.
Published via maven-publish.
The /build directory for the library contains nothing I can identify as an intermediate representation of my common modules, leading me to think that I need to explicitly tell Gradle to produce the files to be included as common in the published package.
As it is, the .aar and .jar files produced in the android and desktop (jvm) modules each look normal, but the published common module is empty.
I need that common module to be populated before I can code against it inside the common module of dependent projects.
Here is the relevant section of my build.gradle.kts. I omit the repository config as it appears to work.
I basically followed the instructions from kotlinlang.org.
I've looked at the maven-publish plugin configuration, the settings for the kotlin-multiplatformm plugin, and the configured project structure.
kotlin version is 1.6.10, unable to update due to Jetbrains Compose dependency.
plugins {
kotlin("multiplatform")
id("com.android.library")
id("maven-publish")
}
kotlin {
android {
publishLibraryVariants = listOf("release", "debug")
}
jvm("desktop") {
compilations.all {
kotlinOptions {
jvmTarget = "11"
}
}
}
val publicationsFromMainHost = listOf(jvm("desktop").name, "kotlinMultiplatform")
publishing {
publications {
matching { it.name in publicationsFromMainHost }.all {
val targetPublication = this#all
tasks.withType<AbstractPublishToMaven>()
.matching { it.publication == targetPublication }
}
}
}
sourceSets {
val commonMain by getting {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.3.2")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
val androidMain by getting {
dependencies {
implementation("androidx.startup:startup-runtime:1.1.1")
}
}
val androidTest by getting {
dependencies {
implementation("junit:junit:4.13.2")
implementation("androidx.test:core:1.4.0")
implementation("androidx.test:runner:1.4.0")
implementation("androidx.test:rules:1.4.0")
implementation("org.robolectric:robolectric:4.6.1")
}
}
val desktopMain by getting
val desktopTest by getting {
dependencies {
implementation("junit:junit:4.13.2")
}
}
}
}
The answer is to manually supply the Kotlin stdlib dependency, rather than relying on the gradle plugin to add it.
When there are only jvm-based builds present, commonMain will be built with platform type of jdk8 rather than common. By making an explicit dependency on stdlib-common, it will be coerced back to the common platform, and then the correct metadata will be created and published.
kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation(kotlin("stdlib-common"))
}
}
}
}

gradle maven publish Pom using kotlin-dsl

I have a multiplatform kotlin library project that publishes to maven and have been updating to the kotlin 1.3 multiplatform model and kotlin-dsl
The previous groovy gradle script has a modifyPom block, and i found an example here. However as soon as I add
val modifyPom : Closure<*> by ext
modifyPom(closureOf<MavenPom> {
// pom code in here
})
I get the same result no matter what is in the pom data, which is that the call of the modifyPom groovy closure breaks the build with a very vague error:
Build file '<path>\build.gradle.kts' line: 47
Open File
In other words the line number of the call of modifyPom groovy Closure, but nothing about the actual error.
I am using Gradle 5.0. Any help appreciated.
So - in Groovy I had this block for configuring POMs, and it worked just fine:
project.publishing.publications.forEach { publication ->
publication.pom.withXml {
def root = asNode()
root.appendNode("name", "libui")
root.appendNode("description", "Kotlin/Native interop to libui: a portable GUI library")
root.appendNode("url", POM_SCM_URL)
root.children().last() + {
licenses {
license {
name "MIT License"
url POM_SCM_URL
distribution "repo"
}
}
developers {
developer {
id "msink"
name "Mike Sinkovsky"
email "msink#permonline.ru"
}
}
scm {
url POM_SCM_URL
connection POM_SCM_CONNECTION
developerConnection POM_SCM_DEV_CONNECTION
}
}
}
}
And how to convert it to Kotlin DSL?
Edit:
Well, was answered in https://github.com/JetBrains/kotlin-native/issues/2372
In Gradle Kotlin DSL it becomes:
project.publishing.publications.withType<MavenPublication>().forEach { publication ->
with(publication.pom) {
withXml {
val root = asNode()
root.appendNode("name", "libui")
root.appendNode("description", "Kotlin/Native interop to libui: a portable GUI library")
root.appendNode("url", POM_SCM_URL)
}
licenses {
license {
name.set("MIT License")
url.set(POM_SCM_URL)
distribution.set("repo")
}
}
developers {
developer {
id.set("msink")
name.set("Mike Sinkovsky")
email.set("msink#permonline.ru")
}
}
scm {
url.set(POM_SCM_URL)
connection.set(POM_SCM_CONNECTION)
developerConnection.set(POM_SCM_DEV_CONNECTION)
}
}
}
This problem was fixed by changing the definition of modifyPom to
val modifyPom : Closure<MavenPom> by ext
That fixed the original problem as posted, and the pom is now being modified. If anyone needs help, add a comment and hopefully I will notice

Unresolved reference: launch

Trying to run some examples for Kotlin coroutines, but can't build my project. I'm using the latest gradle release - 4.1
Any suggestions what to check/fix?
Here is build.gradle
buildscript {
ext.kotlin_version = '1.1.4-3'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin'
apply plugin: 'application'
kotlin {
repositories {
jcenter()
}
experimental {
coroutines 'enable'
}
dependencies {
compile "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.18"
}
}
and the main.kt
fun main(args: Array<String>) {
launch (CommonPool) {
delay(1000L)
println("World!")
}
println("Hello, ")
Thread.sleep(2000L)
}
when I run gradle compileKotlin I get the following
e: /Users/philippgrigoryev/projects/kotlin-coroutines/src/main/kotlin/main.kt: (2, 5): Unresolved reference: launch
e: /Users/philippgrigoryev/projects/kotlin-coroutines/src/main/kotlin/main.kt: (2, 13): Unresolved reference: CommonPool
e: /Users/philippgrigoryev/projects/kotlin-coroutines/src/main/kotlin/main.kt: (3, 9): Unresolved reference: delay`
Launch isn't used anymore directly. The Kotlin documentation suggests using:
fun main() {
GlobalScope.launch { // launch a new coroutine in background and continue
delay(1000L)
println("World!")
}
println("Hello,") // main thread continues here immediately
runBlocking { // but this expression blocks the main thread
delay(2000L) // ... while we delay for 2 seconds to keep JVM alive
}
}
If you are using Coroutines 1.0+, the import is no longer
import kotlinx.coroutines.experimental.*
but
import kotlinx.coroutines.launch
You would need the following in the dependencies closure of your build.gradle (for Coroutines 1.0.1):
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.1'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1"
Like already answered in the comments, the import is missing for the kotlinx.coroutines.experimental.* package. You can have a look at my examples at GitHub if you like.
import kotlinx.coroutines.experimental.*
fun main(args: Array<String>) {
launch(CommonPool) {
delay(1000)
LOG.debug("Hello from coroutine")
}
}
This confused me for a while because the tutorial I am doing shows it used directly... I think they have changed how it is used from a previous version.
I think the trick is that you can only call launch() within a Coroutine scope.
So this does not work:
fun main() {
launch() // not called within coroutine scope
}
Where this will work:
fun main() {
runBlocking {
launch() // called within coroutine scope
}
}
code snippit example
Try this way,
//add this lines to gradle
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$rootProject.kotlinx_coroutines"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$rootProject.kotlinx_coroutines"
class xyz{
private val job = Job()
private val coroutinesScope: CoroutineScope = CoroutineScope(job + Dispatchers.IO)
....
. ...
coroutinesScope.launch {
// task to do
Timber.d("Delete Firebase Instance ID")
}
// clear the job
job.cancel()
}
I am using
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1"
Instead of launch, GlobalScope.launch works.
Given below is the imports:-
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
I met this issue while using kotlinx-corountine-core library, here is my gradle,
buildscript {
ext.kotlin_version = '1.5.21'
ext.kotlin_coroutines_version = '1.3.9'
repositories {
google()
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:3.6.0"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.20'
}
}
// .....
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar", '*.aar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.0'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
}
Then the launch and many other references from kotlin coroutines can't be found. Here is my procedure to solve this problem,
First, find the final dependences under Android Studio. I'm surprised to find that the final kotlin coroutine library was 1.5.0, AND IT SHOULD BE EMPTY!
1.3.9 is also included, but 1.5.0 is greater. So, 1.5.0 will be used finally.
Then I tried to find out the project dependencies by the following command,
>gradlew :app:dependencies
where 'aap' is the project module name.
Then I found it's lifecycle-viewmodel-ktx using it.
So, I tried to upgrade the library to a greater version, 1.6.0. Then, I found it's not empty now and every references work again.
So, to solve it, you need,
find which version of kotlin coroutines core library you are using in your project
investigate what's going on in that library, is that 1.5.0 or empty?
find who introduced this version
try upgrade to a newer version
try this
CoroutineScope(coroutineContext).launch {
}

Resources