Skip to content

Commit 983e463

Browse files
committed
ci(agents): add kmp-maps-build-guide porting and setup skill
1 parent 73006eb commit 983e463

1 file changed

Lines changed: 118 additions & 0 deletions

File tree

  • .agents/skills/kmp-maps-build-guide
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
---
2+
name: kmp-maps-build-guide
3+
description: Comprehensive blueprint and expert guidance for porting libraries and sample sets to Kotlin Multiplatform (KMP) and Compose Multiplatform (CMP), covering build lifecycle, CocoaPods cinterop, Xcode build phase output tracking, and platform UI interoperability.
4+
---
5+
6+
# KMP / CMP Porting & Build Blueprint
7+
8+
This blueprint outlines the essential patterns, build lifecycle steps, and architecture rules for porting an existing Android library or sample catalog to **Kotlin Multiplatform (KMP)** and **Compose Multiplatform (CMP)**.
9+
10+
---
11+
12+
## 1. Porting Architecture & Source Set Organization
13+
14+
When migrating an existing library or sample set to KMP:
15+
16+
```mermaid
17+
graph TD
18+
Common[commonMain<br/>Shared API & Composables] --> Android[androidMain<br/>AndroidView Interop]
19+
Common --> iOS[iosMain / appleMain<br/>UIKit Interop / Cinterop]
20+
```
21+
22+
### A. Source Set Hierarchy (`build.gradle.kts`)
23+
Ensure clear separation between pure state/composables and platform-specific view wrappers:
24+
- **`commonMain`**: Shared data models, public interface definitions (expect/actual), and platform-agnostic Compose UI.
25+
- **`androidMain`**: Android-specific implementations, Google Maps Android SDK wrappers, and `AndroidView` interop.
26+
- **`iosMain` / `appleMain`**: iOS-specific implementations, Cinterop bindings, and `UIKitView` / `UIKitViewController` wrappers.
27+
28+
### B. Cinterop & Pod Linking (`cocoapods` Block)
29+
When wrapping native iOS SDKs (e.g., Google Maps), configure the CocoaPods plugin to generate Cinterop definitions:
30+
```kotlin
31+
kotlin {
32+
iosX64()
33+
iosArm64()
34+
iosSimulatorArm64()
35+
36+
cocoapods {
37+
summary = "Shared KMP Library"
38+
homepage = "https://github.com/..."
39+
ios.deploymentTarget = "16.0" // Match underlying SDK requirements
40+
41+
// Link external iOS dependency
42+
pod("GoogleMaps") {
43+
version = "10.14.0"
44+
extraOpts += listOf("-compiler-option", "-fmodules")
45+
}
46+
}
47+
}
48+
```
49+
50+
---
51+
52+
## 2. Platform UI Interoperability
53+
54+
### A. Embedding Native iOS Views in Compose
55+
Use `UIKitView` or `UIKitViewController` to embed native iOS map/camera controllers inside shared Compose layouts:
56+
```kotlin
57+
@Composable
58+
actual fun PlatformMapView(modifier: Modifier) {
59+
UIKitViewController(
60+
factory = { MyNativeViewController() },
61+
modifier = modifier
62+
)
63+
}
64+
```
65+
66+
### B. Exposing Compose to iOS Sample Apps
67+
Wrap root KMP composables in a `ComposeUIViewController` for seamless ingestion into native `UIViewController` or `UITableView` sample architectures:
68+
```kotlin
69+
fun MainViewController(): UIViewController = ComposeUIViewController {
70+
MySharedSampleScreen()
71+
}
72+
```
73+
74+
---
75+
76+
## 3. iOS Build Lifecycle & Xcode Integration
77+
78+
### A. Pre-Generate Dummy Framework
79+
Before running `pod install` in your sample iOS app, you must generate the initial Kotlin framework:
80+
```bash
81+
./gradlew :<kmp_module_name>:generateDummyFramework
82+
```
83+
*(Prevents CocoaPods from failing with `Kotlin framework doesn't exist yet`)*.
84+
85+
### B. Script Phase Output Tracking (Xcode 16+)
86+
When adding custom **Run Script Build Phases** (e.g., dynamic secrets injection or code generation) to your Xcode targets:
87+
- **Rule**: Always declare the generated source output path (e.g., `$(SRCROOT)/iosApp/DeveloperSecrets.swift`) in the **Output Files** (`output_paths`) of that build phase.
88+
- **Why**: Modern Xcode build systems enforce strict input/output verification during dependency graph analysis and will fail with `Build input file cannot be found` if the output file is undeclared.
89+
90+
### C. Pod Installation & Repo Sync
91+
Ensure your local podspec cache is updated when referencing new SDK versions:
92+
```bash
93+
pod install --repo-update
94+
```
95+
96+
---
97+
98+
## 4. Secrets & Credential Injection
99+
100+
To keep sample repositories secure:
101+
1. Store API keys locally in an uncommitted `secrets.properties` file:
102+
```properties
103+
MAPS_API_KEY=AIzaSy...
104+
```
105+
2. Inject keys via a Gradle task (for Android) or a pre-build Run Script (for iOS) that outputs a Git-ignored configuration struct (`DeveloperSecrets.swift`).
106+
107+
---
108+
109+
## 5. Verification Commands
110+
111+
- **Verify Android Library & Sample App**:
112+
```bash
113+
./gradlew assembleDebug
114+
```
115+
- **Verify iOS XCFramework Compilation**:
116+
```bash
117+
./gradlew :<kmp_module_name>:podPublishDebugXCFramework
118+
```

0 commit comments

Comments
 (0)