Kotlin multiplatform cannot resolved references while gradle sync succeeds - kotlin

When I compile my kotlin multiplatform project I get Unresolved reference on stuffs that I use in the common module. But the gradle synchronisation works fine. You can found my project here
In details:
I followed the tutorial from Jetbrain to build a mobile multiplatform project. Everything works fine.
Then I implemented inside the common module a ktor client to request an api (jsonplaceholder). I added all the required dependencies and everything seems good. All references are resolved, I have no errors.
But when I compile my project with make Project then all the dependencies added to get ktor and so on cannot be resolved.
I guess I have a problem with the configuration of my project, when I run ./gradlew androidDependencies it seems that there is a problem with SharedCode since it is sometimes marked in the command´s output as \--- :SharedCode.
The build.gradle for the project is:
buildscript {
ext.kotlin_version = '1.3.71'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.0-rc01'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
The build.gradle.kts for the common SharedCode module is:
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
plugins {
kotlin("multiplatform")
kotlin("plugin.serialization")
}
kotlin {
//select iOS target platform depending on the Xcode environment variables
val iOSTarget: (String, KotlinNativeTarget.() -> Unit) -> KotlinNativeTarget =
if (System.getenv("SDK_NAME")?.startsWith("iphoneos") == true)
::iosArm64
else
::iosX64
iOSTarget("ios") {
binaries {
framework {
baseName = "SharedCode"
}
}
}
jvm("android")
val serializationVersion = "0.20.0"
val ktorVersion = "1.3.2"
sourceSets["commonMain"].dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-common")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serializationVersion")
implementation("io.ktor:ktor-client-core:$ktorVersion")
implementation("io.ktor:ktor-client-json:$ktorVersion")
implementation("io.ktor:ktor-client-serialization:$ktorVersion")//Kotlinxserializer
}
sourceSets["androidMain"].dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib")
}
}
val packForXcode by tasks.creating(Sync::class) {
val targetDir = File(buildDir, "xcode-frameworks")
/// selecting the right configuration for the iOS
/// framework depending on the environment
/// variables set by Xcode build
val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
val framework = kotlin.targets
.getByName<KotlinNativeTarget>("ios")
.binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
from({ framework.outputDirectory })
into(targetDir)
/// generate a helpful ./gradlew wrapper with embedded Java path
doLast {
val gradlew = File(targetDir, "gradlew")
gradlew.writeText("#!/bin/bash\n"
+ "export 'JAVA_HOME=${System.getProperty("java.home")}'\n"
+ "cd '${rootProject.rootDir}'\n"
+ "./gradlew \$#\n")
gradlew.setExecutable(true)
}
}
tasks.getByName("build").dependsOn(packForXcode)
And the build.gradle for the android app is:
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "com.mpp.mpptest"
minSdkVersion 16
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation project(':SharedCode')
}
Do you know what I am doing wrong?
I read Building Multiplatform Projects with Gradle but it did not help.
The only working project that I found is from KaMPKit. I have set my build.gradle(.kts) files as they are in KaMPKit (see the branch Set_build_gradle_as_KaMPKit) but the `unresolved references´ problem remains.

I fixed my problem. The error came because I did not declare the plugin android.lybrary.
Even if it is not necessary to fix the problem, I have decided to switch my build.gradle files to kotlin DLS, I rewrote all the build.gradle and I made the following changes for the shared module:
I created a AndroidManifest.xml
I added the com.android.library plugins
I added a block android
At the end the build.gradle.kts for the shared module looks like this:
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
plugins {
kotlin("multiplatform")
kotlin("plugin.serialization")
id("kotlinx-serialization")
id("com.android.library")
}
android {
compileSdkVersion(29)
defaultConfig {
minSdkVersion(Versions.min_sdk)
targetSdkVersion(Versions.target_sdk)
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
}
kotlin {
//select iOS target platform depending on the Xcode environment variables
val iOSTarget: (String, KotlinNativeTarget.() -> Unit) -> KotlinNativeTarget =
if (System.getenv("SDK_NAME")?.startsWith("iphoneos") == true)
::iosArm64
else
::iosX64
iOSTarget("ios") {
binaries {
framework {
baseName = "SharedCode"
}
}
}
jvm("android")
sourceSets["commonMain"].dependencies {
implementation(kotlin("stdlib-common", Versions.kotlin))
implementation(Deps.Ktor.commonCore)
implementation(Deps.Ktor.commonJson)
implementation(Deps.Coroutines.common)
implementation(Deps.Ktor.commonSerialization)
}
sourceSets["androidMain"].dependencies {
implementation(kotlin("stdlib", Versions.kotlin))
implementation(Deps.Coroutines.jdk)
implementation(Deps.Ktor.androidSerialization)
}
sourceSets["iosMain"].dependencies {
implementation(Deps.Ktor.iosSerialization)
}
}
val packForXcode by tasks.creating(Sync::class) {
val targetDir = File(buildDir, "xcode-frameworks")
/// selecting the right configuration for the iOS
/// framework depending on the environment
/// variables set by Xcode build
val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
val framework = kotlin.targets
.getByName<KotlinNativeTarget>("ios")
.binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
from({ framework.outputDirectory })
into(targetDir)
/// generate a helpful ./gradlew wrapper with embedded Java path
doLast {
val gradlew = File(targetDir, "gradlew")
gradlew.writeText("#!/bin/bash\n"
+ "export 'JAVA_HOME=${System.getProperty("java.home")}'\n"
+ "cd '${rootProject.rootDir}'\n"
+ "./gradlew \$#\n")
gradlew.setExecutable(true)
}
}
tasks.getByName("build").dependsOn(packForXcode)
All dependency version numbers come from a Dependencies.kt files (see KaMPKit)
All dependencies are now resolved.

Related

(KotlinSourceSet with name 'androidMain' not found.) How can I add android as a build target to a Kotlin Multiplatform project

I am trying to add android() as a build target to a Kotlin Multiplatform library so that I can add a specific library for the android target. All the other targets (jvm, linux, ios) work fine, but android seems to have issues, because the KotlinSourceSet is not being create like the others.
That's where I get the error:
KotlinSourceSet with name 'androidMain' not found.
I wonder, do I have to add the SourceSet manually? Am I missing some crucial build step?
Here is my gradle.build.kts
plugins {
id("maven-publish")
kotlin("multiplatform") version "1.8.0"
}
buildscript {
repositories {
google()
}
dependencies {
classpath ("com.android.tools.build:gradle:4.2.2")
classpath ("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0")
}
}
group = "zzz.xxxx"
version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
}
kotlin {
jvm()
linuxX64("linux")
ios()
android()
sourceSets {
val commonMain by getting {
dependencies {
implementation("...")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
val jvmMain by getting {
dependencies {
implementation("...")
}
}
val androidMain by getting {
dependencies {
implementation ("...")
}
}
val jvmTest by getting
}
}
I tried adding a androidMain folder, but it is not getting recognized as a KotlinSourceSet. Non of the resources online seem to help either.
To add android as a build target your need to setup android-gradle-plugin first.
With example setting of android plugin gradle.build.kts will be:
plugins {
id("maven-publish")
kotlin("multiplatform") version "1.8.0"
id("com.android.library") version "7.3.0" // (1) add plugin
}
//...
// (2) setup plugin
android {
compileSdk = 33
defaultConfig {
minSdk = 24
multiDexEnabled = true
}
sourceSets {
getByName("main") {
manifest.srcFile("src/androidMain/AndroidManifest.xml")
}
}
}
UPDATE
Before you are adding Android Gradle plugin:
Check that Google Maven repository is listed in your settings.gradle(.kts) file
Check the Android Gradle plugin is added to the project build.gradle(.kts) file
Check the Android Gradle plugin is compatible with your Gradle version

kapt/requery not generating ORM files

I'm trying to ressurect a kotlin app that used to Just Work™, i.e., compile straight away, on Ubuntu 16.04.
Part of it is generated code, but i get compilation errors because there is, for instance, no PersonEntity class. So this code fails:
public final void getName(#org.jetbrains.annotations.Nullable()
android.widget.ImageView view, #org.jetbrains.annotations.NotNull()
com.my.app.model.Plus item, #org.jetbrains.annotations.Nullable()
android.widget.ImageView parent, #org.jetbrains.annotations.NotNull()
PersonEntity line) {
}
I have two viable candidates:
Person.java:
package com.my.package.model;
import android.databinding.Observable;
import android.os.Parcelable;
import java.io.Serializable;
import io.requery.Entity;
import io.requery.Key;
import io.requery.Persistable;
#Entity
public interface Person extends Observable, Parcelable, Persistable, Serializable {
#Key
long getID();
int getAge();
...
DbPerson.kt:
package com.my.package.DbObjects
import com.google.gson.annotations.Expose
import com.google.gson.annotations.SerializedName
class DbPerson {
#SerializedName("ID")
#Expose
var id: String =""
#SerializedName("Age")
#Expose
var age: String =""
I see kapt generates a lot of class files, e.g.:
./app/build/tmp/kapt3/incrementalData/debug/com/my/package/DbObjects/DbPerson.class
./app/build/tmp/kapt3/stubs/debug/com/my/package/DbObjects/DbPerson.java
./app/build/tmp/kapt3/stubs/debug/com/my/package/DbObjects/DbPerson.kapt_metadata
...but no PersonEntity.java. Actually, no *Entity* files whatsoever.
I'm not sure if this was because the *.model files are Java instad of kotlin, so i migrated them to kotlin, and got different errors. Maybe because they're interfaces and not regular classes? But then where are the other *Entity* files?
This is my build.gradle:
buildscript {
ext {
setup = [
compileSdk: 27,
buildTools: "27.0.1",
minSdk : 14,
targetSdk : 27
]
versions = [
supportLib: "27.0.1"
]
kotlin_version = '1.3.31'
}
repositories {
google()
jcenter() // w: JCenter is at end of life
maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
}
dependencies {
classpath 'com.android.tools.build:gradle:4.2.2'
//classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.0"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath "com.jaredsburrows:gradle-spoon-plugin:1.4.0"
}
}
allprojects {
repositories {
google()
jcenter()
maven { url "https://jitpack.io" }
maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
And my app/build.gradle:
apply plugin: "com.android.application"
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: "com.jaredsburrows.spoon"
android {
lintOptions {
abortOnError false
}
compileSdkVersion 27
defaultConfig {
multiDexEnabled true
applicationId "com.my.package"
minSdkVersion 19
targetSdkVersion 26
versionCode 9 //db_version too
versionName "2.31"
//testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
testInstrumentationRunner "com.my.app.activities.CustomTestRunner"
resValue "string", "app_build_number", (System.getenv("BUILD_NUMBER") ?: "IDE")
resValue "string", "server_address", "1.2.3.4"
project.ext.set("archivesBaseName", "MyAppName-" + System.getenv("BRANCH_NAME") + "-v" + defaultConfig.versionName + "." + (System.getenv("BUILD_NUMBER") as Integer ?: 0).toString())
}
signingConfigs {
release {
storeFile file("myKey.jks")
storePassword 'mypassword'
keyAlias 'mykeyalias'
keyPassword 'mypassword'
}
}
buildTypes {
release {
resValue "string", "server_address", ""
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
no_wifi_check
{
resValue "string", "app_build_number", "NOWIFI"
signingConfig signingConfigs.release
}
debug {
resValue "string", "server_address", "1.2.3.4"
}
}
buildFeatures {
dataBinding true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8' // Java 7 not supported by kotlinOptions jvmTarget
}
}
dependencies {
implementation 'javax.xml.bind:jaxb-api:2.3.1'
implementation 'xml-apis:xml-apis:2.0.2'
implementation 'xerces:xercesImpl:2.12.0'
implementation 'com.android.support:multidex:1.0.3'
androidTestImplementation('com.android.support:multidex-instrumentation:1.0.3') {
exclude group: 'com.android.support', module: 'multidex'
}
implementation fileTree(dir: 'libs', include: ['*.jar'])
//implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.31"
/* ^ w: Plugin version (1.5.0) is not the same as library version (1.3.31)
A newer version of org.jetbrains.kotlin:kotlin-stdlib-jdk8 than 1.3.31 is available: 1.4.31 */
implementation 'com.android.support:support-v4:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.0.2' // w: A newer version of com.android.support.constraint:constraint-layout than 1.0.2 is available: 2.0.4
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.android.support:cardview-v7:27.1.1'
implementation 'io.reactivex.rxjava2:rxjava:2.1.1'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
//retrofit
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
//requery
implementation 'io.requery:requery:1.4.1'
implementation 'io.requery:requery-android:1.4.1' // for android
//annotationProcessor 'io.requery:requery-processor:1.4.1'
kapt("io.requery:requery-processor:1.4.1")
//Picasso
implementation 'com.squareup.picasso:picasso:2.5.2'
//okhttp
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
implementation 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0'
//AndroidSlidingUpPanel
implementation 'com.sothree.slidinguppanel:library:3.4.0'
//
implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
//MaterialDrawer
implementation("com.mikepenz:materialdrawer:6.0.9#aar") {
transitive = true
}
//required support lib modules
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:recyclerview-v7:27.1.1'
//implementation "com.android.support:support-annotations:${versions.supportLib}"
implementation "com.android.support:support-annotations"
implementation 'com.android.support:design:27.1.1'
// the sample uses more advanced functions of the fastadapter
// https://github.com/mikepenz/FastAdapter/
implementation 'com.mikepenz:fastadapter-commons:3.2.8#aar'
// used to generate the Open Source section
// https://github.com/mikepenz/AboutLibraries
implementation('com.mikepenz:aboutlibraries:6.0.0#aar') {
transitive = true
}
//used to provide different itemAnimators for the RecyclerView
//https://github.com/mikepenz/ItemAnimators
implementation 'com.mikepenz:itemanimators:1.0.1#aar'
// used to provide the MiniDrawer to normal Drawer crossfade effect via a SlidingPane layout
// --> https://github.com/mikepenz/MaterialDrawer/blob/develop/app/src/main/java/com/mikepenz/materialdrawer/app/MiniDrawerActivity.java
// https://github.com/mikepenz/Crossfader
implementation 'com.mikepenz:crossfader:1.5.1#aar'
// used to provide the two step crossfade DrawerLayout. Which allows to have a mini layout which transforms to a normal layout within the drawer
// --> https://github.com/mikepenz/MaterialDrawer/blob/develop/app/src/main/java/com/mikepenz/materialdrawer/app/CrossfadeDrawerLayoutActvitiy.java
// https://github.com/mikepenz/CrossfadeDrawerLayout
implementation('com.mikepenz:crossfadedrawerlayout:1.0.1#aar')
// icon fonts used inside the sample
// https://github.com/mikepenz/Android-Iconics
implementation 'com.mikepenz:google-material-typeface:3.0.1.1.original#aar'
implementation 'com.mikepenz:fontawesome-typeface:4.7.0.1#aar'
implementation 'com.mikepenz:octicons-typeface:3.0.0.1#aar'
implementation('com.mikepenz:materialdrawer:6.0.9#aar') { transitive = true }
// icon fonts used inside the sample
// https://github.com/mikepenz/Android-Iconics
implementation 'com.mikepenz:google-material-typeface:3.0.1.1.original#aar'
implementation 'com.mikepenz:fontawesome-typeface:4.7.0.1#aar'
implementation 'com.mikepenz:octicons-typeface:3.0.0.1#aar'
//Toasty
implementation 'com.github.GrenderG:Toasty:1.2.8'
//android fab
//compile 'uk.co.markormesher:android-fab:2.0.0'
//FloatingActionButton
implementation 'com.github.clans:fab:1.6.4'
implementation 'com.jaredrummler:colorpicker:1.0.2'
implementation 'com.fasterxml.jackson.core:jackson-core:2.7.3'
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.7.3'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.7.3'
androidTestImplementation 'com.android.support.test.espresso:espresso-contrib:3.0.2', {
exclude group: 'com.android.support', module: 'support-annotations'
exclude group: 'com.android.support', module: 'support-v4'
exclude group: 'com.android.support', module: 'design'
exclude group: 'com.android.support', module: 'recyclerview-v7'
}
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-contrib:3.0.2'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test:rules:1.0.2'
androidTestImplementation 'com.android.support.test.uiautomator:uiautomator-v18:2.1.3'
androidTestImplementation 'com.squareup.spoon:spoon-client:1.6.4'
}
kapt {
//generateStubs = true
useBuildCache = false
correctErrorTypes = true
}
apply plugin: 'spoon'
// This section is optional
spoon {
// for debug output
debug = true
// To run a single test class
className = 'fully.qualified.TestCase'
// To run a single method in TestCase
methodName = 'testMyApp'
// To execute the tests device by device */
sequential = true
// To grant permissions to Android M >= devices */
grantAllPermissions = true
}
android.applicationVariants.all { variant ->
def applicationId = variant.applicationId
def adb = android.getAdbExe().toString()
def variantName = variant.name.capitalize()
def grantPermissionTask = tasks.create("grant${variantName}Permissions") { doLast {
"${adb} devices".execute().text.eachLine {
if (it.endsWith("device")) {
def device = it.split()[0]
println "Granting permissions on devices ${device}"
"${adb} -s ${device} shell pm grant ${applicationId} android.permission.CAMERA".execute()
"${adb} -s ${device} shell pm grant ${applicationId} android.permission.ACCESS_FINE_LOCATION".execute()
"${adb} -s ${device} shell pm grant ${applicationId} android.permission.WRITE_EXTERNAL_STORAGE".execute()
"${adb} -s ${device} shell pm grant ${applicationId} android.permission.READ_EXTERNAL_STORAGE".execute()
}
}
}
}
}
I assume there's a mismatch somewhere between plugin versions, Java version, kotlin version, gradle, etc... but i can't place it.
** EDIT **
The same project builds on:
Windows 10 VM
Android Studio 4.1
whichever JDK is in C:\Program Files\Android\Android Studio\jre (the release file has JAVA_VERSION="1.8.0_242")
but not on:
Ubuntu Xenial VM
Android Studio 4.2.1
whichever JDK is in ${HOME}/android-studio/jre (the release file has JAVA_VERSION="11.0.8", which is too different to make sense).

SQLDelight: Unresolved reference AndroidSqliteDriver in Kotlin Multiplatform App

I try add sqldelight to my Kotlin Multiplatform App, but AndroidSqliteDriver unresolved reference. I dont understand why.
I clear cache and regenerate all, but it dont work too.
AndroidSqliteDriver:
package com.rompos.deactivator
import com.squareup.sqldelight.android.AndroidSqliteDriver
import android.content.Context
lateinit var appContext: Context
actual fun createDB() : Server {
val driver = AndroidSqliteDriver(Server.Schema, appContext, "Server.db")
return Server(driver)
}
build.gradle(common):
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
plugins {
kotlin("multiplatform")
id("com.squareup.sqldelight")
}
kotlin {
//select iOS target platform depending on the Xcode environment variables
val iOSTarget: (String, KotlinNativeTarget.() -> Unit) -> KotlinNativeTarget =
if (System.getenv("SDK_NAME")?.startsWith("iphoneos") == true)
::iosArm64
else
::iosX64
iOSTarget("ios") {
binaries {
framework {
baseName = "SharedCode"
}
}
}
jvm("android")
// Common Main
sourceSets["commonMain"].dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-common")
implementation("io.ktor:ktor-client-core:1.3.2")
implementation("com.squareup.sqldelight:runtime:1.4.0")
}
// Android Main
sourceSets["androidMain"].dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib")
implementation("com.squareup.sqldelight:android-driver:1.4.0") {
exclude(group = "com.squareup.sqldelight", module = "runtime-jdk")
}
}
// iOS Main
sourceSets["iosMain"].dependencies {
implementation("com.squareup.sqldelight:native-driver:1.4.0")
}
}
build.gradle(android):
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlinx-serialization'
apply plugin: 'com.squareup.sqldelight'
android {
compileSdkVersion 30
buildToolsVersion "30.0.1"
defaultConfig {
applicationId "com.rompos.deactivator"
minSdkVersion 26
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner
"androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-
optimize.txt'), 'proguard-rules.pro'
}
}
packagingOptions {
exclude 'META-INF/*.kotlin_module'
}
buildFeatures {
dataBinding true
}
}
dependencies {
implementation project(':SharedCode')
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "androidx.core:core-ktx:1.3.1"
implementation "androidx.appcompat:appcompat:1.2.0"
implementation "com.google.android.material:material:1.2.0"
implementation "androidx.constraintlayout:constraintlayout:1.1.3"
implementation
"androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
implementation "androidx.navigation:navigation-fragment-ktx:2.3.0"
implementation "androidx.navigation:navigation-ui-ktx:2.3.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-
android:1.3.7"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-
runtime:0.20.0"
implementation "io.ktor:ktor-client-android:1.3.2"
implementation "com.squareup.sqldelight:android-
driver:$sqldelight_version"
testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-
core:3.2.0'
}
build.gradle(project):
buildscript {
ext {
ext.kotlin_version = '1.3.72'
sqldelight_version = "1.4.0"
}
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-
plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-
serialization:$kotlin_version"
classpath "com.squareup.sqldelight:gradle-
plugin:$sqldelight_version"
}
}
allprojects {
repositories {
google()
jcenter()
maven { url "https://kotlin.bintray.com/kotlinx" }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
I use:
gradle: 6.1.1
gradle plugin: 4.0.1
kotlin: 1.3.72
upd: Add code
you only have a jvm target jvm("android") and not an android target. you need an android library or application target to use the android library.
EDIT: To add an android target:
//build.gradle(common)
plugins {
...
// assuming your building a library. use application otherwise
id("com.android.library")
id("kotlin-android")
}
...
android {
// fill in your library or app info here
}
kotlin {
android { // creates androidMain/Test source sets
// ex: publishLibraryVariants("release", "debug")
}
ios() { ... }
val commonMain by getting { ... }
val androidMain by getting { ... }
...
}
Make sure you're using at least Android Studio 4.1.
You should only need to include the SQLDelight plugin in your common build.gradle.
build.gradle
...
apply plugin: "com.squareup.sqldelight" in the common build.gradle
...
sourceSets {
commonMain.dependencies {
...
// SQL Delight
implementation "com.squareup.sqldelight:runtime:${Versions.sqlDelight}"
implementation "com.squareup.sqldelight:coroutines-extensions:${Versions.sqlDelight}"
}
androidMain.dependencies {
...
// SQL Delight
implementation "com.squareup.sqldelight:android-driver:${Versions.sqlDelight}"
implementation "com.squareup.sqldelight:coroutines-extensions-jvm:${Versions.sqlDelight}"
}
iOSMain.dependencies {
...
// SQL Delight
implementation "com.squareup.sqldelight:ios-driver:${Versions.sqlDelight}"
}
}

Create a Github library mix of jvm and Kotlin multiplatform

I am trying to build an Android Library and I have the following:
Github Repo for the library
Library 1: Kotlin native/multiplatform code that can compile to Android and iOS
Library 2: Kotlin/JVM code dependent on Library 1
Example App: App using Library 2 and Library 1
Personal Android Project
Dependent on the Github Library above
On my personal project I only have:
implementation 'com.github.username:myrepo:0.5'
Issues
The private Android project is loading android library (Library 2) but the multiplatform kotlin models and functions (Library 1) are not accessible.
Note that the example app of the library is working fine. I suspect that the jitpack.io is not publishing the artifacts correctly. Any idea on how to troubleshoot this? Is there anything that should be done to the gradle files to solve the problem?
I would like to have the multiplatform library published alone. I tried to access it from a multiplatform Kotlin module but I am getting "Unable to resolve dependencies". This is what I was trying:
implementation 'com.github.username.myrepo:library1_moduleName:0.1'
Gradle for Library 1 multiplatform:
plugins {
kotlin("multiplatform")
}
kotlin {
//select iOS target platform depending on the Xcode environment variables
val iOSTarget: (String, KotlinNativeTarget.() -> Unit) -> KotlinNativeTarget =
if (System.getenv("SDK_NAME")?.startsWith("iphoneos") == true)
::iosArm64
else
::iosX64
iOSTarget("ios") {
binaries {
framework {
baseName = "library1"
freeCompilerArgs.add("-Xobjc-generics")
}
}
}
jvm("android")
sourceSets["commonMain"].dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-common")
}
sourceSets["androidMain"].dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib")
}
}
val packForXcode by tasks.creating(Sync::class) {
val targetDir = File(buildDir, "xcode-frameworks")
/// selecting the right configuration for the iOS
/// framework depending on the environment
/// variables set by Xcode build
val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
val framework = kotlin.targets
.getByName<KotlinNativeTarget>("ios")
.binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
from({ framework.outputDirectory })
into(targetDir)
/// generate a helpful ./gradlew wrapper with embedded Java path
doLast {
val gradlew = File(targetDir, "gradlew")
gradlew.writeText(
"#!/bin/bash\n"
+ "export 'JAVA_HOME=${System.getProperty("java.home")}'\n"
+ "cd '${rootProject.rootDir}'\n"
+ "./gradlew \$#\n"
)
gradlew.setExecutable(true)
}
}
tasks.getByName("build").dependsOn(packForXcode)
Gradle for library 2
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
repositories {
google()
jcenter()
maven { url 'https://jitpack.io' }
}
compileSdkVersion 29
buildToolsVersion "29.0.0"
defaultConfig {
minSdkVersion 19
targetSdkVersion 29
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
api project(":library1")
}
I suggest you change your build.gradle configuration for targeting android/ Change it to
plugins {
kotlin("multiplatform")
id("com.android.library")
id("maven-publish")
}
android {
compileSdkVersion 29
buildToolsVersion "29.0.0"
defaultConfig {
minSdkVersion 19
targetSdkVersion 29
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
kotlin {
//select iOS target platform depending on the Xcode environment variables
val iOSTarget: (String, KotlinNativeTarget.() -> Unit) -> KotlinNativeTarget =
if (System.getenv("SDK_NAME")?.startsWith("iphoneos") == true)
::iosArm64
else
::iosX64
iOSTarget("ios") {
binaries {
framework {
baseName = "library1"
freeCompilerArgs.add("-Xobjc-generics")
}
}
}
// jvm("android")
android {
publishLibraryVariants("release")
}
sourceSets["commonMain"].dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-common")
}
sourceSets["androidMain"].dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib")
}
}
val packForXcode by tasks.creating(Sync::class) {
val targetDir = File(buildDir, "xcode-frameworks")
/// selecting the right configuration for the iOS
/// framework depending on the environment
/// variables set by Xcode build
val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
val framework = kotlin.targets
.getByName<KotlinNativeTarget>("ios")
.binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
from({ framework.outputDirectory })
into(targetDir)
/// generate a helpful ./gradlew wrapper with embedded Java path
doLast {
val gradlew = File(targetDir, "gradlew")
gradlew.writeText(
"#!/bin/bash\n"
+ "export 'JAVA_HOME=${System.getProperty("java.home")}'\n"
+ "cd '${rootProject.rootDir}'\n"
+ "./gradlew \$#\n"
)
gradlew.setExecutable(true)
}
}
tasks.getByName("build").dependsOn(packForXcode)
create an AndroidManifest.xml file for library1 under src/main/AndroidManifest.xml
<manifest package="library1"/>
you can now push your projet to github, create a tag and wait for jitpack to do its magic
When you want to use it in library2, under the dependencies section, just add
implementation 'com.github.username.myrepo:library1-android:0.1' //for android
Think you may need to enable meta-data for the multi-platform library; in settings.gradle:
enableFeaturePreview('GRADLE_METADATA')
As well as configuring the library for Maven (it is unclear how you publish it to GitHub, as the build.gradle does not feature any of that as automation). Even when publishing it to GitHub instead of mavenLocal(), it likely needs to provide some kind of meta-data... as "Unable to resolve dependencies" might hint for, assuming that it exists under the referenced package name.
apply plugin: 'maven-publish'
group 'com.github.username'
version '1.0.0'
Configuration api is merely good for dependencies, which are being referenced by multiple modules; everything else (any single occurance) should be implementation. I mean, I find the library 2 build.gradle confusing, because on top it reads maven { url 'https://jitpack.io' } (without actually referencing a remote dependency) and then later it reads api project(":library1") (which defintely is a local dependency).

Can't import dependencies for Kotlin multi platform common

I am trying out Kotlin multi-platform and trying to setup all my dependencies for it. Starting with commonMain
I am trying to add Koin and Ktor dependencies to the common portion but I cant seem to be able to use any of them.
This is my Gradle script
plugins {
id 'org.jetbrains.kotlin.multiplatform' version '1.3.61'
}
repositories {
google()
jcenter()
mavenCentral()
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 29
defaultConfig {
applicationId 'org.jetbrains.kotlin.mpp_app_android'
minSdkVersion 15
targetSdkVersion 29
versionCode 1
versionName '1.0'
testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner'
}
buildTypes {
release {
minifyEnabled false
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'org.koin:koin-android:2.0.1'
implementation 'org.koin:koin-androidx-viewmodel:2.0.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.1.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
}
kotlin {
android("android")
// This is for iPhone emulator
// Switch here to iosArm64 (or iosArm32) to build library for iPhone device
iosX64("ios") {
binaries {
framework()
}
}
sourceSets {
commonMain {
dependencies {
implementation kotlin('stdlib-common')
implementation 'org.koin:koin-ktor:2.0.1'
implementation 'org.koin:koin-core:2.0.1'
// HTTP
implementation "io.ktor:ktor-client-core:1.2.6"
implementation "io.ktor:ktor-client-json:1.2.6"
implementation "io.ktor:ktor-client-serialization:1.2.6"
// Coroutines
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.2.1"
}
}
commonTest {
dependencies {
implementation kotlin('test-common')
implementation kotlin('test-annotations-common')
}
}
androidMain {
dependencies {
implementation kotlin('stdlib')
}
}
androidTest {
dependencies {
implementation kotlin('test')
implementation kotlin('test-junit')
}
}
iosMain {
}
iosTest {
}
}
}
// This task attaches native framework built from ios module to Xcode project
// (see iosApp directory). Don't run this task directly,
// Xcode runs this task itself during its build process.
// Before opening the project from iosApp directory in Xcode,
// make sure all Gradle infrastructure exists (gradle.wrapper, gradlew).
task copyFramework {
def buildType = project.findProperty('kotlin.build.type') ?: 'DEBUG'
def target = project.findProperty('kotlin.target') ?: 'ios'
dependsOn kotlin.targets."$target".binaries.getFramework(buildType).linkTask
doLast {
def srcFile = kotlin.targets."$target".binaries.getFramework(buildType).outputFile
def targetDir = getProperty('configuration.build.dir')
copy {
from srcFile.parent
into targetDir
include 'app.framework/**'
include 'app.framework.dSYM'
}
}
}
In the Sample.kt file that was generated when I created the project I tried to setup Koin in the main method
fun main() {
startKoin {
// declare modules
modules(myModule)
}
println(hello())
}
but startKoin cannot be resolved.
I cleaned/rebuilt the project, did a gradle sync and still cant import koin or any other dependency so what am I missing
Koin is not multiplatform capable. We have [multiplatform forks][1], but would need to chat about which to use and what version. We're still discussing multiplatform strategy.
Ktor's dependencies are more complex than that. See below. I removed your other dependencies for clarity, but you should leave them obviously :)
sourceSets {
commonMain {
dependencies {
implementation "io.ktor:ktor-client-core:1.2.6"
implementation "io.ktor:ktor-client-json:1.2.6"
implementation "io.ktor:ktor-client-serialization:1.2.6"
}
}
androidMain {
dependencies {
implementation "io.ktor:ktor-client-core-jvm:1.2.6"
implementation "io.ktor:ktor-client-json-jvm:1.2.6"
implementation "io.ktor:ktor-client-serialization-jvm:1.2.6"
}
}
iosMain {
dependencies {
implementation "io.ktor:ktor-client-ios:1.2.6"
implementation "io.ktor:ktor-client-core-native:1.2.6"
implementation "io.ktor:ktor-client-json-native:1.2.6"
implementation "io.ktor:ktor-client-serialization-native:1.2.6"
}
}
}
[1]: https://github.com/kpgalligan/koin/tree/kpg/khan