How to add Realm to Android target of Kotlin multiplatform library project? - gradle

I'm trying to add Realm to the android target of my Kotlin multiplatform library but I get this error:
Please initialize at least one Kotlin target in 'library (:library)'.
Read more https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#setting-up-targets
I can add Realm to any Android project without issues, but when I try to add it to a multiplatform library it doesn't work. Here's my build.gradle.kts:
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
plugins {
kotlin("multiplatform")
id("com.android.library")
id("realm-android")
}
kotlin {
val iOSTarget: (String, KotlinNativeTarget.() -> Unit) -> KotlinNativeTarget =
if (System.getenv("SDK_NAME")?.startsWith("iphoneos") == true)
::iosArm64
else
::iosX64
android()
iOSTarget("ios") {
binaries {
}
}
sourceSets {
val commonMain by getting
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val androidMain by getting
val androidTest by getting {
dependencies {
implementation(kotlin("test-junit"))
implementation("junit:junit:4.13")
implementation("io.mockk:mockk:1.10.6")
}
}
val iosMain by getting
}
}
val artifactName = "library"
android {
compileSdkVersion(29)
defaultConfig {
minSdkVersion(24)
targetSdkVersion(29)
versionCode = 1
versionName = "1.0"
base.archivesBaseName = "${artifactName}-${versionName}"
}
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
}
If I remove the line id("realm-android") it builds fine, but there's no Realm.

Related

Kotlin/Native `Could not find :kotlin-native-prebuilt-windows-x86_64`

My goal is to make a Kotlin Multiplatform module for Android and iOS. It is being built using Gradle as a dependency of an Android app on Windows. When only Android is a target it builds just fine, but if any native targets are added it fails:
Could not resolve all dependencies for configuration ':shared-mobile-lib:detachedConfiguration3'.
The project declares repositories, effectively ignoring the repositories you have declared in the settings.
You can figure out how project repositories are declared by configuring your build to fail on project repositories.
Could not find :kotlin-native-prebuilt-windows-x86_64:1.7.10.
Required by:
project :shared-mobile-lib
How do I fix this?
Here is the build.gradle.kt:
plugins {
kotlin("multiplatform")
id("com.android.library")
}
repositories {
google()
mavenCentral()
}
group = "com.agragps.mobile"
version = "0.1.0"
kotlin {
android()
// The below targets fail
iosArm32 {
binaries {
framework {
baseName = "library"
}
}
}
iosArm64 {
binaries {
framework {
baseName = "library"
}
}
}
iosX64 {
binaries {
framework {
baseName = "library"
}
}
}
androidNativeArm64()
androidNativeArm32()
sourceSets {
val commonMain by getting
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
val androidMain by getting {
dependencies {
implementation("com.google.android.material:material:1.8.0")
}
}
val androidTest by getting {
dependencies {
implementation("junit:junit:4.13.2")
}
}
val iosArm32Main by getting
val iosArm32Test by getting
val iosArm64Main by getting
val iosArm64Test by getting
val iosX64Main by getting
val iosX64Test by getting
val androidNativeArm64Main by getting
val androidNativeArm64Test by getting
val androidNativeArm32Main by getting
val androidNativeArm32Test by getting
}
}
android {
compileSdkVersion(33)
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdkVersion(21)
targetSdkVersion(33)
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
}
This is based on a sample project from Intellij IDEA, I verified Kotlin Native was installed under .konan and tried configuring the build to fail for project repositories (the repository specified is ivy) with no luck.
Eventually worked after upgrading dependencies (on another machine).
Not sure which dependency it was. Ended up upgrading:
Gradle (7.4.2 -> 7.5)
com.android.tools.build:gradle (7.0.4 -> 7.3.1)
Had to re-run the build a few times on the other machine as well.

Kotlin multiplatform publish with dokka and sources

I am struggling to publish a Kotlin multiplatform project properly to maven (for now mavenLocal). I can add the dependency to another multiplatform project and use the code but I don't get any documentation and I am not sure if I am doing something wrong or if that is simply not possible at the moment.
From what I understand you cannot use the normal javadoc because it is bound to Java which does not make sense in a multiplatform environment. I read somewhere that in that case you should use the html version of dokka. I can see that I get a "javadoc.jar" with content to my mavenLocal but still in the IDE in an example project where I add my KMP library as a dependency, I don't see any documentation.
Also, the code decompiling seems to be weird. I guess somehow the sources are also not properly resolved.
According to the documentation everything should automatically and perfectly work by simply adding the maven-publish and the dokka plugin. But it seems like this is not the case and actually nothing is working as I'd expect it :D
Does anyone know, how to properly set that up?
My gradle file looks like this:
plugins {
kotlin("multiplatform") version "1.6.21"
id("org.jetbrains.kotlinx.benchmark") version "0.4.2"
id("org.jetbrains.dokka") version "1.6.21"
`maven-publish`
signing
}
group = "io.github.quillraven.fleks"
version = "1.4-KMP-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_1_8
repositories {
mavenCentral()
}
kotlin {
targets {
jvm {
compilations {
all {
kotlinOptions {
jvmTarget = "1.8"
}
}
val main by getting { }
// custom benchmark compilation
val benchmarks by compilations.creating {
defaultSourceSet {
dependencies {
// Compile against the main compilation's compile classpath and outputs:
implementation(main.compileDependencyFiles + main.output.classesDirs)
}
}
}
}
withJava()
testRuns["test"].executionTask.configure {
useJUnitPlatform()
}
}
}
js(BOTH) {
browser { }
}
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.")
}
sourceSets {
val commonMain by getting { }
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
val jvmMain by getting
val jvmTest by getting
val jvmBenchmarks by getting {
dependsOn(commonMain)
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.4.2")
implementation("com.badlogicgames.ashley:ashley:1.7.4")
implementation("net.onedaybeard.artemis:artemis-odb:2.3.0")
}
}
val jsMain by getting
val jsTest by getting
val nativeMain by getting
val nativeTest by getting
}
}
benchmark {
targets {
register("jvmBenchmarks")
}
}
val javadocJar by tasks.registering(Jar::class) {
archiveClassifier.set("javadoc")
from(tasks.dokkaHtml)
}
publishing {
repositories {
maven {
url = if (project.version.toString().endsWith("SNAPSHOT")) {
uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")
} else {
uri("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/")
}
credentials {
username = System.getenv("OSSRH_USERNAME")
password = System.getenv("OSSRH_TOKEN")
}
}
}
publications {
val kotlinMultiplatform by getting(MavenPublication::class) {
version = project.version.toString()
groupId = project.group.toString()
artifactId = "Fleks"
artifact(javadocJar)
pom {
name.set("Fleks")
description.set("A lightweight entity component system written in Kotlin.")
url.set("https://github.com/Quillraven/Fleks")
scm {
connection.set("scm:git:git#github.com:quillraven/fleks.git")
developerConnection.set("scm:git:git#github.com:quillraven/fleks.git")
url.set("https://github.com/quillraven/fleks/")
}
licenses {
license {
name.set("MIT License")
url.set("https://opensource.org/licenses/MIT")
}
}
developers {
developer {
id.set("Quillraven")
name.set("Simon Klausner")
email.set("quillraven#gmail.com")
}
}
}
}
signing {
useInMemoryPgpKeys(System.getenv("SIGNING_KEY"), System.getenv("SIGNING_PASSWORD"))
sign(kotlinMultiplatform)
}
}
}
// only sign if version is not a SNAPSHOT release.
// this makes it easier to publish to mavenLocal and test the packed version.
tasks.withType<Sign>().configureEach {
onlyIf { !project.version.toString().endsWith("SNAPSHOT") }
}
When I run the publishToMavenLocal gradle task then I get following directories in my .m2 folder:
When I then create an example project and add it as a dependency, then I don't see any quick documentation and also the decompiling is not working properly:
I was finally able to publish to mavenCentral. Not sure if this is the best way and correct way to do it, but it seems to work. Here is my build.gradle.kts. The important part is in the publications sections. For whatever reason it is not sufficient to have the "root" folder setup properly. I also had to adjust the pom, javadoc and signing of every single publication, too.
#file:Suppress("UNUSED_VARIABLE")
plugins {
kotlin("multiplatform") version "1.6.21"
id("org.jetbrains.kotlinx.benchmark") version "0.4.2"
id("org.jetbrains.dokka") version "1.6.21"
`maven-publish`
signing
}
group = "io.github.quillraven.fleks"
version = "1.4-KMP-RC1"
java.sourceCompatibility = JavaVersion.VERSION_1_8
repositories {
mavenCentral()
}
kotlin {
targets {
jvm {
compilations {
all {
kotlinOptions {
jvmTarget = "1.8"
}
}
val main by getting { }
// custom benchmark compilation
val benchmarks by compilations.creating {
defaultSourceSet {
dependencies {
// Compile against the main compilation's compile classpath and outputs:
implementation(main.compileDependencyFiles + main.output.classesDirs)
}
}
}
}
withJava()
testRuns["test"].executionTask.configure {
useJUnitPlatform()
}
}
}
js(BOTH) {
browser { }
}
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.")
}
sourceSets {
val commonMain by getting { }
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
val jvmMain by getting
val jvmTest by getting
val jvmBenchmarks by getting {
dependsOn(commonMain)
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.4.2")
implementation("com.badlogicgames.ashley:ashley:1.7.4")
implementation("net.onedaybeard.artemis:artemis-odb:2.3.0")
}
}
val jsMain by getting
val jsTest by getting
val nativeMain by getting
val nativeTest by getting
}
}
benchmark {
targets {
register("jvmBenchmarks")
}
}
val javadocJar by tasks.registering(Jar::class) {
archiveClassifier.set("javadoc")
from(tasks.dokkaHtml)
}
publishing {
repositories {
maven {
url = if (project.version.toString().endsWith("SNAPSHOT")) {
uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")
} else {
uri("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/")
}
credentials {
username = System.getenv("OSSRH_USERNAME")
password = System.getenv("OSSRH_TOKEN")
}
}
}
publications {
val kotlinMultiplatform by getting(MavenPublication::class) {
// we need to keep this block up here because
// otherwise the different target folders like js/jvm/native are not created
version = project.version.toString()
groupId = project.group.toString()
artifactId = "Fleks"
}
}
publications.forEach {
if (it !is MavenPublication) {
return#forEach
}
// We need to add the javadocJar to every publication
// because otherwise maven is complaining.
// It is not sufficient to only have it in the "root" folder.
it.artifact(javadocJar)
// pom information needs to be specified per publication
// because otherwise maven will complain again that
// information like license, developer or url are missing.
it.pom {
name.set("Fleks")
description.set("A lightweight entity component system written in Kotlin.")
url.set("https://github.com/Quillraven/Fleks")
scm {
connection.set("scm:git:git#github.com:quillraven/fleks.git")
developerConnection.set("scm:git:git#github.com:quillraven/fleks.git")
url.set("https://github.com/quillraven/fleks/")
}
licenses {
license {
name.set("MIT License")
url.set("https://opensource.org/licenses/MIT")
}
}
developers {
developer {
id.set("Quillraven")
name.set("Simon Klausner")
email.set("quillraven#gmail.com")
}
}
}
signing {
useInMemoryPgpKeys(System.getenv("SIGNING_KEY"), System.getenv("SIGNING_PASSWORD"))
sign(it)
}
}
}
// only sign if version is not a SNAPSHOT release.
// this makes it easier to publish to mavenLocal and test the packed version.
tasks.withType<Sign>().configureEach {
onlyIf { !project.version.toString().endsWith("SNAPSHOT") }
}
Here is my example gradle file that publishes a kotlin multiplatform project with sources and javadocs to a maven repository.
The project source is here: https://github.com/danbrough/misc_demos/tree/master/kotlin_multiplatform_dokka
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
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")
id("org.jetbrains.dokka")
id("com.android.library")
`maven-publish`
}
group = "dokka.test"
version = "0.0.1"
buildscript {
repositories {
mavenCentral()
gradlePluginPortal()
}
}
repositories {
mavenCentral()
google()
}
kotlin {
jvm()
android()
linuxX64()
macosX64()
sourceSets {
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
}
val posixMain by sourceSets.creating {}
targets.withType<KotlinNativeTarget>() {
compilations["main"].defaultSourceSet.dependsOn(posixMain)
}
}
tasks.withType<AbstractTestTask>() {
testLogging {
events = setOf(
TestLogEvent.PASSED, TestLogEvent.SKIPPED, TestLogEvent.FAILED
)
exceptionFormat = TestExceptionFormat.FULL
showStandardStreams = true
showStackTraces = true
}
outputs.upToDateWhen {
false
}
}
tasks.withType(KotlinCompile::class) {
kotlinOptions {
jvmTarget = "11"
}
}
tasks.dokkaHtml.configure {
outputDirectory.set(buildDir.resolve("dokka"))
}
val javadocJar by tasks.registering(Jar::class) {
archiveClassifier.set("javadoc")
from(tasks.dokkaHtml)
}
publishing {
repositories {
maven(project.buildDir.resolve("m2").toURI()) {
name = "m2"
}
}
publications.forEach {
if (it !is MavenPublication) {
return#forEach
}
it.artifact(javadocJar)
}
}
android {
compileSdk = 33
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
namespace = project.group.toString()
defaultConfig {
minSdk = 23
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
signingConfigs.register("release") {
storeFile = File(System.getProperty("user.home"), ".android/keystore")
keyAlias = "keyAlias"
storePassword = System.getenv("KEYSTORE_PASSWORD") ?: ""
keyPassword = System.getenv("KEYSTORE_PASSWORD") ?: ""
}
lint {
abortOnError = false
}
buildTypes {
getByName("debug") {
//debuggable(true)
}
getByName("release") {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
)
signingConfig = signingConfigs.getByName("release")
}
}
}

Error to compile ios project with kotlin multiplatform

I have implemented kotlin multiplatform in an existing ios project and I have these problems
When I compile the application for the simulator an error occurs in the build phases script.
Error: Could not find or load main class org.gradle.wrapper.GradleWrapperMain
Caused by: java.lang.ClassNotFoundException: org.gradle.wrapper.GradleWrapperMain
Command PhaseScriptExecution failed with a nonzero exit code
When I remove the script the compiled for simulator works 🤔. I can run the simulator
Another error is when I want to archive the project. Says it was built for iOS simulator 🤯
My build.gradle.kts
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
plugins {
kotlin("multiplatform")
kotlin("native.cocoapods")
kotlin("plugin.serialization")
id("com.android.library")
id("kotlin-android-extensions")
id("com.squareup.sqldelight")
}
repositories {
gradlePluginPortal()
google()
jcenter()
mavenCentral()
maven {
url = uri("https://dl.bintray.com/kotlin/kotlin-eap")
}
}
dependencies {
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.2.0")
}
configurations {
create("compileClasspath")
}
android {
compileSdkVersion(29)
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdkVersion(24)
targetSdkVersion(29)
versionCode = 1
versionName = "1.0"
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
}
}
}
val libName = "shared"
kotlin {
android()
ios {
binaries.framework(libName)
}
val coroutinesVersion = "1.4.1-native-mt"
val serializationVersion = "1.0.0-RC"
val ktorVersion = "1.4.0"
val sqlDelightVersion = "1.4.3"
val reactive_version = "1.1.18"
sourceSets {
val commonMain by getting {
dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-common")
// Coroutines
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.3.2")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:$serializationVersion")
// KTOR
implementation("io.ktor:ktor-client-core:$ktorVersion")
implementation("io.ktor:ktor-client-json:$ktorVersion")
implementation("io.ktor:ktor-client-serialization:$ktorVersion")
// SQLDELIGHT
implementation("com.squareup.sqldelight:runtime:$sqlDelightVersion")
// Reactive
implementation("com.badoo.reaktive:reaktive:$reactive_version")
}
}
val androidMain by getting {
dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib")
implementation("androidx.core:core-ktx:1.3.2")
implementation("io.ktor:ktor-client-android:$ktorVersion")
implementation("com.squareup.sqldelight:android-driver:$sqlDelightVersion")
implementation("androidx.lifecycle:lifecycle-extensions:2.2.0")
}
}
val iosMain by getting {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.3.2")
// HTTP
implementation("io.ktor:ktor-client-ios:$ktorVersion")
implementation("com.squareup.sqldelight:native-driver:$sqlDelightVersion")
}
}
all {
languageSettings.apply {
progressiveMode = true
useExperimentalAnnotation("kotlin.RequiresOptIn")
useExperimentalAnnotation("kotlinx.coroutines.ExperimentalCoroutinesApi")
}
}
}
}
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)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
val targetDir = File(buildDir, "xcode-frameworks")
from({ framework.outputDirectory })
into(targetDir)
}
tasks.getByName("build").dependsOn(packForXcode)
sqldelight {
database("SmileduDataBase") {
packageName = "com.example.smiledu"
schemaOutputDirectory = file("src/commonMain/db/databases")
}
}
Another error is when I want to archive the project. Says it was built for iOS simulator 🤯
Hi. I faced this issue a few times and the only work around I got is that we need to run this ./gradlew clean in android studio terminal before creating an archive for iOS and then try to create archive and it should work. You can find more details on this here :- https://youtrack.jetbrains.com/issue/KT-40907
When I compile the application for the simulator an error occurs in the build phases script.
For this it looks like your wrapper is corrupted probably am not so sure about this. Does android app runs perfectly ? Also you can have a look here once :- How to resolve java.lang.ClassNotFoundException: org.gradle.wrapper.GradleWrapperMain error?

Publish Kotlin MPP metadata with Gradle Kotlin DSL

I have created a Kotlin MPP to share Json utilities between JVM and JS. All the code lies in the common source set and I have configured the necessary targets with their respective dependencies. Without further configuration I'm able to use the utilities from both JVM and JS but not from the common source set of another MPP, which has to do with the way Gradle handles metadata.
I already found the solution (taken from https://medium.com/xorum-io/crafting-and-publishing-kotlin-multiplatform-library-to-bintray-cbc00a4f770)
afterEvaluate {
project.publishing.publications.all {
groupId = group
if (it.name.contains('metadata')) {
artifactId = "$libraryName"
} else {
artifactId = "$libraryName-$name"
}
}
}
and I also got it to work with the Gradle Kotlin DSL:
afterEvaluate {
publishing.publications.all {
this as MavenPublication
artifactId = project.name + "-$name".takeUnless { "metadata" in name }.orEmpty()
}
}
However, this doesn't feel quite right yet.
There is no such code snippet in the official documentation.
The documentation advertises that a single dependency from the common source set should suffice to automatically resolve target specific dependencies: https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#metadata-publishing. I had to add the dependency for each target, respectively, for it to work.
this as MavenPublication is necessary because Publication has no field artifactId.
I use project.name instead of libraryName.
Is this even remotely the right way to do things or am I missing some other option which would make the whole process trivial?
Right now I'm using Kotlin 1.3.72 and Gradle 5.2.1 with enableFeaturePreview("GRADLE_METADATA") in settings.gradle.kts. I also tried it with Gradle 6.5.1 (latest) but it behaves exactly the same.
For now I'm glad that it's working at all but I suspect there is a cleaner way to do this. I'd really appreciate if someone with a bit more Gradle expertise could clear things up for me or point me into the right direction.
Edit:
gradle.build.kts for completeness. Although there isn't much going on here.
group = "org.example"
version = "1.0-SNAPSHOT"
plugins {
kotlin("multiplatform") version "1.3.72"
`maven-publish`
}
repositories {
mavenCentral()
}
kotlin {
jvm()
sourceSets {
val commonMain by getting {
dependencies {
implementation(kotlin("stdlib-common"))
}
}
val jvmMain by getting {
dependencies {
implementation(kotlin("stdlib"))
}
}
}
}
There wasn't really a problem after all. The solution is to simply add enableFeaturePreview("GRADLE_METADATA") to the consuming project too.
According to https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#metadata-publishing this shouldn't be necessary:
In earlier Gradle versions starting from 5.3, the module metadata is
used during dependency resolution, but publications don't include any
module metadata by default. To enable module metadata publishing, add
enableFeaturePreview("GRADLE_METADATA") to the root project's
settings.gradle file.
Weirdly it only works when both publishing project and consuming project have metadata enabled, even when both use the latest Gradle version.
enableFeaturePreview("GRADLE_METADATA") is enabled by default in latest gradle.
According to this you need to substitute "kotlinMultiplatform" by "" an empty string.
I finally managed to accomplish publishing to bintray with maven-publish plugin only, without outdated bintray library.
Here is my full maven.publish.gradle.kts:
import java.io.FileInputStream
import java.util.*
import org.gradle.api.publish.PublishingExtension
apply(plugin = "maven-publish")
val fis = FileInputStream("local.properties")
val properties = Properties().apply {
load(fis)
}
val bintrayUser = properties.getProperty("bintray.user")
val bintrayApiKey = properties.getProperty("bintray.apikey")
val bintrayPassword = properties.getProperty("bintray.gpg.password")
val libraryVersion: String by project
val publishedGroupId: String by project
val artifact: String by project
val bintrayRepo: String by project
val libraryName: String by project
val bintrayName: String by project
val libraryDescription: String by project
val siteUrl: String by project
val gitUrl: String by project
val licenseName: String by project
val licenseUrl: String by project
val developerOrg: String by project
val developerName: String by project
val developerEmail: String by project
val developerId: String by project
project.group = publishedGroupId
project.version = libraryVersion
afterEvaluate {
configure<PublishingExtension> {
publications.all {
val mavenPublication = this as? MavenPublication
mavenPublication?.artifactId =
"${project.name}${"-$name".takeUnless { "kotlinMultiplatform" in name }.orEmpty()}"
}
}
}
configure<PublishingExtension> {
publications {
withType<MavenPublication> {
groupId = publishedGroupId
artifactId = artifact
version = libraryVersion
pom {
name.set(libraryName)
description.set(libraryDescription)
url.set(siteUrl)
licenses {
license {
name.set(licenseName)
url.set(licenseUrl)
}
}
developers {
developer {
id.set(developerId)
name.set(developerName)
email.set(developerEmail)
}
}
organization {
name.set(developerOrg)
}
scm {
connection.set(gitUrl)
developerConnection.set(gitUrl)
url.set(siteUrl)
}
}
}
}
repositories {
maven("https://api.bintray.com/maven/${developerOrg}/${bintrayRepo}/${artifact}/;publish=1") {
credentials {
username = bintrayUser
password = bintrayApiKey
}
}
}
}
And build.gradle.kts:
plugins {
id("kotlin-multiplatform")
}
kotlin {
sourceSets {
jvm()
js() {
browser()
nodejs()
}
linuxX64()
linuxArm64()
mingwX64()
macosX64()
iosArm64()
iosX64()
val commonMain by getting {
dependencies {
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val jsMain by getting {
dependencies {
}
}
val jsTest by getting {
dependencies {
implementation(kotlin("test-js"))
}
}
val jvmMain by getting {
dependencies {
}
}
val jvmTest by getting {
dependencies {
implementation(kotlin("test"))
implementation(kotlin("test-junit"))
}
}
val nativeMain by creating {
dependsOn(commonMain)
dependencies {
}
}
val linuxX64Main by getting {
dependsOn(nativeMain)
}
val linuxArm64Main by getting {
dependsOn(nativeMain)
}
val mingwX64Main by getting {
dependsOn(nativeMain)
}
val macosX64Main by getting {
dependsOn(nativeMain)
}
val iosArm64Main by getting {
dependsOn(nativeMain)
}
val iosX64Main by getting {
dependsOn(nativeMain)
}
}
}
apply(from = "maven.publish.gradle.kts")
Please note, there are bintray.user and bintray.apikey properties in local.properties file.
Also gradle.properties contains rest listed properties above:
libraryVersion = 0.5.22
libraryName = MultiplatformCommon
libraryDescription = Kotlin multiplatform extensions
publishedGroupId = com.olekdia
artifact = multiplatform-common
bintrayRepo = olekdia
bintrayName = multiplatform-common
siteUrl = https://gitlab.com/olekdia/common/libraries/multiplatform-common
gitUrl = https://gitlab.com/olekdia/common/libraries/multiplatform-common.git
.........
kotlin.mpp.enableGranularSourceSetsMetadata = true
systemProp.org.gradle.internal.publish.checksums.insecure = true
If you haven't created organisation in bintray you need to change in this url:
https://api.bintray.com/maven/${developerOrg}/${bintrayRepo}/${artifact}/;publish=1
developerOrg by bintrayUser, where the last one is your user name at bintray.com

Kotlin build FatFramework with defined minimum iOS version

I want to deploy my multiplatform project to .framework with supported iOS architecture using FatFramework using this gradle configuration. It's work but I founded in info.plist that it have default MinimumOSVersion to iOS 9 so I can't used my library below that version.
Is there any way / possible to configure the minimum iOS version for my lib ?
import org.jetbrains.kotlin.gradle.tasks.FatFrameworkTask
plugins {
id("org.jetbrains.kotlin.multiplatform") version "1.3.61"
id("maven-publish")
id("com.jfrog.bintray") version "1.8.4"
id("org.jetbrains.dokka") version "0.10.0"
}
group = "com.example.lib"
version = "1.0.0"
repositories {
mavenCentral()
jcenter()
}
kotlin {
jvm()
val iosX64 = iosX64("ios")
val iosArm64 = iosArm64("iosArm64")
val iosArm32 = iosArm32("iosArm32")
val frameworkName = "EXAMPLE-LIB"
configure(listOf(iosX64, iosArm64, iosArm32)) {
binaries.framework {
baseName = frameworkName
}
}
sourceSets {
named("commonMain") {
dependencies {
implementation(kotlin("stdlib-common"))
implementation(kotlin("stdlib-jdk7"))
implementation(kotlin("stdlib-jdk8"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.3.0-RC")
implementation(kotlin("reflect"))
}
}
named("commonTest") {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
implementation(kotlin("reflect"))
}
}
named("jvmMain") {
dependencies {
implementation(kotlin("stdlib-jdk8"))
}
}
named("jvmTest") {
dependencies {
implementation(kotlin("test"))
implementation(kotlin("test-junit"))
}
}
val iosMain by getting {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.3.0-RC")
implementation("io.ktor:ktor-client-ios:1.2.6")
}
}
val iosArm64Main by getting {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.3.0-RC")
implementation("io.ktor:ktor-client-ios:1.2.6")
}
}
val iosArm32Main by getting {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.3.0-RC")
implementation("io.ktor:ktor-client-ios:1.2.6")
}
}
}
val debugFatFramework by tasks.creating(FatFrameworkTask::class) {
baseName = frameworkName
from(
iosArm32.binaries.getFramework("debug"),
iosArm64.binaries.getFramework("debug"),
iosX64.binaries.getFramework("debug")
)
destinationDir = buildDir.resolve("fat-framework/debug")
group = "Universal framework"
description = "Builds a debug universal (fat) framework"
}
val releaseFatFramework by tasks.creating(FatFrameworkTask::class) {
baseName = frameworkName
from(
iosArm32.binaries.getFramework("release"),
iosArm64.binaries.getFramework("release"),
iosX64.binaries.getFramework("release")
)
destinationDir = buildDir.resolve("fat-framework/release")
group = "Universal framework"
description = "Builds a release universal (fat) framework"
}
val zipDebugFatFramework by tasks.creating(Zip::class) {
dependsOn(debugFatFramework)
from(debugFatFramework)
from("LICENSE.md")
}
val zipReleaseFatFramework by tasks.creating(Zip::class) {
dependsOn(releaseFatFramework)
from(releaseFatFramework)
from("LICENSE.md")
}
}
tasks.register<Exec>("generateThriftModels") {
executable = "java"
args(
"-jar", "thrifty-compiler.jar",
"--lang", "kotlin",
"--omit-generated-annotations",
"--list-type=kotlin.collections.ArrayList",
"--set-type=kotlin.collections.LinkedHashSet",
"--out", "src/commonMain/kotlin",
"--path", "./thrift/",
"./thrift/nativeapp.thrift"
)
}
This parameter is derived from the Kotlin/Native's compiler properties list. It can be found there:~/.konan/kotlin-native-prebuilt-<hostname>-<version>/konan/konan.properties. The value responsible for the MinimumOSVersion is the osVersionMin.<target_name>. This should be set per target. It can be changed manually, and this new value will be used by all your projects. Also, after 1.4.30 there is a new way to specify compiler properties. See in this document for example. I would recommend using it as follows:
...
configure(listOf(iosX64, iosArm64, iosArm32)) {
binaries.framework {
freeCompilerArgs += listOf("-Xoverride-konan-properties=osVersionMin.ios_arm32=7;osVersionMin.ios_arm64=7;osVersionMin.ios_x64=7")
}
}
...

Resources