Professional Documents
Culture Documents
Nate Ebel
@n8ebel
fi
How can your team start sharing
code using Kotlin Multiplatform?
Where are we going?
• 8 Android developers
• 7 iOS developers
• Localized in 40 languages
Tip #2
“Start small”
Validating KMP in production
iOS
Shared
Where will this new code live?
Brownfield iOS Project Greenfield KMP Project
iOS Shared
iOS Shared
Shared
How to structure this new KMP project?
Shared
How to structure this new KMP project?
Greenfield KMP Project
Shared
iosMain
commonMain
Kotlin Multiplatform Targets
Shared
iosMain
androidMain
commonMain
Are these the right targets for our use case?
Greenfield KMP Project
Shared
iosMain
commonMain
Configuring Build Targets
analytics/build.gradle.kts
plugins { kotlin(“multiplatform”) }
/
/
Configuring Build Targets
analytics/build.gradle.kts
plugins { kotlin(“multiplatform”) }
kotlin {
jvm()
iosX64()
iosArm64()
}
/
/
Configuring Build Targets
kotlin {
jvm()
iosX64()
iosArm64()
}
Configuring Build Targets
kotlin {
jvm()
iosX64()
iosArm64()
}
Configuring Build Targets
kotlin {
jvm()
iosX64()
iosArm64()
sourceSets {
}
Configuring Build Targets
kotlin {
jvm()
iosX64()
iosArm64()
sourceSets {
dependsOn(commonMain)
iosX64Main.dependsOn(this)
iosArm64Main.dependsOn(this)
}
Primary questions
How do we build and scale a KMP solution?
Shared
iosMain
commonMain
What if we want multiple multiplatform artifacts?
Greenfield KMP Project
iosMain
commonMain
What if we want multiple multiplatform artifacts?
Greenfield KMP Project
Analytics
iosMain
commonMain
What if we want multiple multiplatform artifacts?
Greenfield KMP Project
Analytics
Analytics
DTOs
Networking
Recommendations
What if we want multiple multiplatform artifacts?
Greenfield KMP Project
Analytics
DTOs
Android
Networking
Recommendations
What if we want multiple multiplatform artifacts?
Greenfield KMP Project
Analytics
DTOs
iOS
Networking
Recommendations
What if we want multiple multiplatform artifacts?
Greenfield KMP Project
Analytics
DTOs
iOS
Networking
Recommendations
What if we want multiple multiplatform artifacts?
Greenfield KMP Project
Analytics
DTOs
Shared iOS
Networking
Recommendations
Configuring a Composite Module
Combine separate modules into 1 for iOS consumption
shared/build.gradle.kts
plugins { kotlin(“multiplatform”) }
/
/
Configuring a Composite Module
Combine separate modules into 1 for iOS consumption
shared/build.gradle.kts
plugins { kotlin(“multiplatform”) }
kotlin {
}
/
/
Configuring a Composite Module
Combine separate modules into 1 for iOS consumption
shared/build.gradle.kts
plugins { kotlin(“multiplatform”) }
kotlin {
.forEach { target
}
/
/
-
>
Configuring a Composite Module
Combine separate modules into 1 for iOS consumption
shared/build.gradle.kts
plugins { kotlin(“multiplatform”) }
kotlin {
.forEach { target
target.binaries.framework {
xcf.add(this)
export(project(“:analytics”))
export(project(“:network”))
transitiveExport = true
}
/
/
-
>
Configuring a Composite Module
Combine separate modules into 1 for iOS consumption
kotlin {
.forEach { target
target.binaries.framework {
xcf.add(this)
export(project(“:analytics”))
export(project(“:network”))
transitiveExport = true
}
-
>
Configuring a Composite Module
Combine separate modules into 1 for iOS consumption
kotlin {
.forEach { target
target.binaries.framework {
xcf.add(this)
export(project(“:analytics”))
export(project(“:network”))
transitiveExport = true
}
-
>
Configuring a Composite Module
Combine separate modules into 1 for iOS consumption
kotlin {
. . .
}
Configuring a Composite Module
Combine separate modules into 1 for iOS consumption
kotlin {
. . .
sourceSets {
. . .
iosMain by creating {
dependencies {
api(project(“:analytics”))
api(project(“:network”))
Primary questions
How do we build and scale a KMP solution?
• Android / JVM
• .jar / .aar
• maven-publish plugin
• iOS
• XCFramework
• Cocoapods
analytics/build.gradle.kts
plugins {
kotlin(“multiplatform”)
id(“maven-publish”)
}
/
/
Building Android Output Artifacts
analytics/build.gradle.kts
plugins {
kotlin(“multiplatform”)
id(“maven-publish”)
id(“com.android.library”)
/
/
Building Android Output Artifacts
analytics/build.gradle.kts
plugins {
kotlin(“multiplatform”)
id(“maven-publish”)
id(“com.android.library”)
/
/
Building Android Output Artifacts
analytics/build.gradle.kts
plugins {
kotlin {
android {
publishAllLibraryVariants()
/
/
Building JVM/Android Output Artifacts
shared/build.gradle.kts
plugins {
kotlin(“multiplatform”)
id(“com.chromaticnoise.multiplatform-swiftpackage”)
}
/
/
Building iOS Swift Package
shared/build.gradle.kts
plugins {
. . .
}
/
/
Building iOS Swift Package
shared/build.gradle.kts
plugins {
. . .
multiplatformSwiftPackage {
swiftToolsVersion(“5.3”)
packageName(rootProject.name)
distributionMode { local() }
}
/
/
Building iOS Swift Package
Android
allProjects {
repositories {
mavenLocal()
}
~/.m2 }
build.gradle
Local Deployment for iOS
Consuming local Swift Package
iOS
Xcode
shared/output/swiftpackage
Primary questions
How do we build and scale a KMP solution?
• How to deploy the .jar and .aar les to internal Artifactory server?
analytics/build.gradle.kts
plugins {
id(“com.jfrog.artifactory”)
/
/
Deploying Android Artifacts
analytics/build.gradle.kts
plugins {
. . .
/
/
Deploying Android Artifacts
analytics/build.gradle.kts
plugins { . . . }
/
/
Deploying Android Artifacts
analytics/build.gradle.kts
plugins { . . . }
hand-wavy pseudocode
artifactory {
}
/
/
/
/
Deploying Android Artifacts
analytics/build.gradle.kts
plugins { . . . }
hand-wavy pseudocode
artifactory {
}
/
/
/
/
Deploying Android Artifacts
analytics/build.gradle.kts
plugins { . . . }
hand-wavy pseudocode
artifactory {
repository {
setProperty(“repoKey”, “<repo>”)
setProperty(“username”, “<username>”)
setProperty(“password”, “<password>”)
setProperty(“maven”, true)
}
/
/
/
/
Deploying Android Artifacts
hand-wavy pseudocode
artifactory {
repository {
setProperty(“repoKey”, “<repo>”)
setProperty(“username”, “<username>”)
setProperty(“password”, “<password>”)
setProperty(“maven”, true)
}
/
/
Deploying Android Artifacts
hand-wavy pseudocode
artifactory {
repository {
setProperty(“repoKey”, “<repo>”)
setProperty(“username”, “<username>”)
setProperty(“password”, “<password>”)
setProperty(“maven”, true)
}
/
/
Deploying Android Artifacts
hand-wavy pseudocode
artifactory {
repository {
setProperty(“repoKey”, “<repo>”)
setProperty(“username”, “<username>”)
setProperty(“password”, “<password>”)
setProperty(“maven”, true)
defaults {
}
/
/
Consuming Android Artifact
build.gradle.kts
repositories {
app/build.gradle.kts
dependencies {
implementation(“com.yourpackage.analytics:1.0.0”)
/
/
/
/
Building the Project with GitHub Actions
./gradlew publishToArtifactory
Deploying Swift Packages
premise/mobile-shared-swift-package
shared.xcframework
Package.swift
.gitignore
Deploying Swift Packages
import PackageDescription
name: “shared”,
platforms: [ .iOS(.v13)],
products: [
shared.xcframework .library(
name: “shared”,
targets: [“shared”]
),
Package.swift ],
targets: [
.binaryTarget(
path: “./shared.xcframework”
) Package.swift
/
/
Consuming Swift Packages
Xcode
Building the Project with GitHub Actions
./gradlew publishToArtifactory
Building the Project with GitHub Actions
clone
commit, push & tag
./gradlew publishToArtifactory
mobile-shared-swift-package swiftpackage
Primary questions
How do we build and scale a KMP solution?
fi
Swift Package Generation
• Less fully-featured
• All Mobile developers can build both iOS and Android projects
Tip #5
• Get feedback from both iOS and Android teams early, and often
Nate Ebel
@n8ebel