I am seeing the following error when trying to compile using gradle.
Supertypes of the following classes cannot be resolved. Please make sure you have the required dependencies in the classpath:
class com.zaxxer.hikari.HikariDataSource, unresolved supertypes: javax.sql.DataSource
Adding -Xextended-compiler-checks argument might provide additional information.
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
//kotlin("jvm") version "1.6.0"
}
group = "com.jasin"
version = "0.0.1"
dependencies {
//api(files("libs/jdbc-stdext-2.0.jar"))
implementation("org.ktorm:ktorm-core:3.4.1")
implementation("org.ktorm:ktorm-support-mysql:3.4.1")
implementation("mysql:mysql-connector-java:8.0.25")
implementation("com.zaxxer:HikariCP:5.0.1")
implementation("org.slf4j:slf4j-api:1.7.36")
implementation("org.slf4j:slf4j-simple:1.7.36")
testImplementation(kotlin("test"))
}
tasks.test {
useJUnit()
}
tasks.withType<KotlinCompile>() {
kotlinOptions.jvmTarget = "11"
}
If I uncomment the following line
//api(files("libs/jdbc-stdext-2.0.jar"))
I get the following type errors
module jdbc.stdext reads package javax.sql from both jdbc.stdext and java.sql
If I recomment this line and try to build again(without cleaning the project), it works. As soon as I clean the project the error reappears. What is exactly going on here and how can I fix this? Any help would be appreciated.
edit: I should add that this is a multi-module project and it wasn't till I tried to define module-info.java files in separate modules that this error appeared. But the error is specific to one module, the module that I use to access my database that uses connection pooling with hikaricp.
module-info.java file
module com.cobis.db {
requires kotlin.stdlib;
requires com.zaxxer.hikari;
requires ktorm.core;
exports com.cobis.db;
exports com.cobis.db.entities;
exports com.cobis.db.utilities;
}
Related
I have a working KMM application, and I have a java module, mymodule, that I created with File->New->Module->Java or Kotlin library.
The module exists at the top level beside androidApp, iosApp and shared. In my settings.gradle.kts I have include(":mymodule").
I want to use mymodule in the shared module. So I go into the shared module's build.gradle.kts and I try to include my module in commonMain:
kotlin {
...
sourceSets {
val commonMain by getting {
dependencies {
implementation(project(":mymodule"))
}
}
...
}
...
}
...
And the error is Could not resolve MyKMMApplication:mymodule:unspecified and:
Could not resolve project :mymodule.
Required by:
project :shared
Things I've tried
I can put dependencies { implementation(project(":mymodule")) } at the bottom of shared's build.gradle.kts and but still the same error appears
As to test if there's other problems, I can also import mymodule into the Android project without problems
I can include implementation("com.squareup.sqldelight:runtime:1.5.3") in commonMain and see those classes in the shared module no problem
The docs say you can include another multiplatform module, but nothing about a normal module.
How can I include a modules into KMM's shared module as a dependency?
So, the module you include into shared needs to be a multiplatform module. It's build.gradle.kts file should look something like this:
plugins {
id("org.jetbrains.kotlin.multiplatform")
}
kotlin {
jvm()
iosX64()
iosArm32()
iosArm64()
}
And it's project structure should look something like: mymodule/src/commonMain/kotlin/com/example/mymodule/.
I have followed the Kotlin documentation for adding iOS dependencies. In my case the dependency is a pre-compiled framework provided through a third party. So I have followed the case for framework without cocoapod.
I placed my MyFramework.def file in /src
language = Objective-C
modules = MyFramework
package = MyFramework
Then I added the following to the build.gradle.kts in the Kotlin object
```
ios {
binaries {
framework {
baseName = "shared"
}
}
}
iosArm64() {
compilations.getByName("main") {
val JWBLe by cinterops.creating {
// Path to .def file
defFile("src/nativeInterop/cinterop/MyFramework.def")
compilerOpts("-framework", "MyFramework", "-F/Users/user/Projects/MyFramework/ios/SDK")
}
}
binaries.all {
// Tell the linker where the framework is located.
linkerOpts("-framework", "MyFramework", "-F/Users/user/Projects/MyFramework/ios/SDK")
}
}
sourceSets {
val commonMain by getting
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val androidMain by getting {
dependencies {
implementation("com.google.android.material:material:1.2.1")
}
}
val androidTest by getting {
dependencies {
implementation(kotlin("test-junit"))
implementation("junit:junit:4.13")
}
}
val iosMain by getting
val iosTest by getting
}
Then I build the project. The library does indeed get seen and I see that in External Libraries, there is a shared-cinterop-MyFramework.klib
However, when I try to import this package into my code under src/iosMain/kotlin/com.example.testapp.shared/platform.kt
I get unresolved error for the library. It seems like I should also need to add something to sourceSets? But I am unsure.
First of all, I got to notice that the Gradle script is incorrect. In this case, the iosArm64 target was declared twice - by the target shortcut and once again where you configure the cinterop. To avoid this duplication, it would be better to configure cinterop like that:
ios()
val iosArm = targets.getByName("iosArm64") as org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
// A bit dirty cast, but as I'm sure iosArm64 is the Native target, it should be fine. Needed to make highlighting below work as expected.
iosArm.apply {
compilations.getByName("main") {
val JWBLe by cinterops.creating {
// Path to .def file
defFile("src/nativeInterop/cinterop/MyFramework.def")
compilerOpts("-framework", "MyFramework", "-F/Users/user/Projects/MyFramework/ios/SDK")
}
}
binaries.all {
// Tell the linker where the framework is located.
linkerOpts("-framework", "MyFramework", "-F/Users/user/Projects/MyFramework/ios/SDK")
}
}
However, this adjustment won't help with accessing cinterop bindings from the iosMain. In the current state of commonizer, it can share only platform libraries. So anyway, moving all code utilizing those bindings into the src/iosArm64Main folder is the best option available at the moment. Here go an issue from the official tracker to upvote and subscribe - Support commonization of user-defined libraries.
So after some playing around I found the answer.
The dependency was set for a module of iosArm64 which is not available to the iosMain.
I created another folder src/iosArm64Main and placed the source file there. At that point it was able to resolve the library.
In build.gradle.kts file, I include this code on the top line. Then I use KotlinCompilerVesion.VERSION below.
import org.jetbrains.kotlin.config.KotlinCompilerVersion
Some code works fine, but some code failed:
It seems like only plugins block can not enable this import.
Here works fine:
dependencies {
Implementation(kotlin("stdlib-jdk7", KotlinCompilerVersion.VERSION))
Implementation(kotlin("test", KotlinCompilerVersion.VERSION))
}
Here always wrong:
plugins {
id("com.android.application")
kotlin("android")
kotlin("android.extensions")
/*
* Error: Unresolved reference: KotlinCompilerVersion
*/
id("kotlinx-serialization") version KotlinCompilerVersion.VERSION
/*
* Error: Unresolved reference: KotlinCompilerVersion
*/
id("kotlinx-serialization") version "$KotlinCompilerVersion.VERSION"
/*
* Error: Unresolved reference: KotlinCompilerVersion
*/
id("kotlinx-serialization") version "${KotlinCompilerVersion.VERSION}"
}
How can I use it correctly in here, without declare an ext.xxxVersion var?
Yes, the syntax of the plugins DSL is limited because Gradle parses it before parsing the rest of the file, which requires the definition to be static (no references to variables, constants, etc., pretty much no code is allowed). See Limitations of the plugins DSL for details.
The way I handle defining Kotlin version only once is by actually using the version I specify in the plugins block as canonical in other sections of the file (I picked this up from this blog post by Simon Wirtz) like so:
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper
val kotlinVersion = plugins.getPlugin(KotlinPluginWrapper::class.java)
.kotlinPluginVersion
plugins {
kotlin("jvm") version "1.3.30"
}
dependencies {
implementation(platform(kotlin("bom", kotlinVersion)))
implementation(kotlin("stdlib-jdk8"))
}
But yeah, in the plugins block it needs to be static and unfortunately repeated if needed.
Update: I actually just learned it's possible to use constants in the plugins DSL, but they must be defined before Gradle parses the build.gradle.kts file, i.e. from buildSrc. I noticed this in the fuel library. In essence, create buildSrc/build.gradle.kts with the following contents:
plugins {
`kotlin-dsl`
}
repositories {
jcenter()
}
Then create buildSrc/src/main/kotlin/Constants.kt with the following contents:
object Kotlin {
const val version = "1.3.30"
}
And then you'll be able to use the following in your main build.gradle.kts:
plugins {
kotlin("jvm") version Kotlin.version
}
I am doing a multiplatform project.
A part of my gradle file looks like this
...
kotlin {
jvm()
jvm("api")
js()
mingwX64("mingw")
sourceSets {
...
val jvmMain by getting {
dependencies {
implementation ("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
}
}
val jvmTest by getting {
dependencies {
implementation ("org.jetbrains.kotlin:kotlin-test")
implementation ("org.jetbrains.kotlin:kotlin-test-junit")
}
}
val apiMain by getting {
dependencies {
dependsOn(jvmMain)
}
}
val jsMain by getting {
dependencies {
implementation ("org.jetbrains.kotlin:kotlin-stdlib-js")
}
}
...
}
}
Now in the commonsMain sources I get an IDE error (red underline) that says "expected class Sample has no actual declaration in apiMain", but apiMain depends on jvmMain which has the actual declaration.
I don't think I need an actual declaration in apiMain since I already have one in jvm.
Should I take a different approach in setting-up my source sets?
Anyway the project compiles fine and I can run apiMain, but the IDE error really annoys me.
This is a known IDE bug. See YouTrack ticket here.
For now, you can use #Suppress("NO_ACTUAL_FOR_EXPECT") to get rid of the warning in your IDE. I wouldn't really recommend it though, because you'll get a runtime crash instead of a compile-time error if you're missing any actual implementations.
They should be under the same package name.
Also check if your package name is the same as the one you get the error
expected class Sample has no actual declaration in apiMain
You need to have the package apiMain.
In my case I had
And I had to create both folders in resources
In my case, it turns out that something in my ".idea" folder had gotten corrupted. I closed Android Studio, deleted that directory from the root of my project and then reopened the project. The .idea file was automatically re-created and my problem was gone.
I figured this out because creating a new KMM app using the wizard didn't have the same error that I was seeing with expect/actual classes.
This error means that class TestUtil is not on the classpath and the compiler can not find it. I came across such error hundred times before and there was missing Jar or wrong written class names, but now I just don't know what is wrong.
In my buildSrc dir I have custom Task and I made test for it:
package com.example.core.tasks;
import spock.lang.Specification
import org.gradle.api.Project
import org.gradle.util.TestUtil
public class GetInfoTaskTest extends Specification {
def "check files"(){
given:
def project = TestUtil.createRootProject()
when:
GetInfoTask getInfo = project.tasks.create("getInfo", GetInfoTask)
then:
getInfo instanceof GetInfoTask.class
}
}
In the build script in the buildSrc dir:
dependencies {
compile localGroovy()
testCompile 'org.spockframework:spock-core:0.7-groovy-1.8'
testCompile gradleApi()
}
Error:
GetInfoTaskTest.groovy: 4: unable to resolve class org.gradle.util.TestUtil
# line 3, column 1.
import org.gradle.util.TestUtil
^
I checked that this TestUtil is not internal. I still don't know why gradle can not find it.
TestUtil is an internal class. You can't use it in your own code.