作者简介
Derek,携程资深研发经理,关注Native技术、跨平台领域。
如何在KMM项目中配置iOS的依赖 KMM工程的CI/CD环境搭建和配置 常见的集成问题的解决方法

import platform.UIKit.UIDevice
class IOSPlatform: Platform {
override val name: String = UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion
}
复制

language = Objective-C
headers = AAA.h BBB.h
compilerOpts = -I/xxx(/xxx为h文件所在目录)
复制
compilations["main"].cinterops.create(name) {
defFile = project.file("src/nativeInterop/cinterop/xxx.def")
packageName = "com.xxx.ioscall"
}
复制
import com.xxx.ioscall.AAA
复制

language = Objective-C
package = com.yy.FA
headers = xxx/TestLocalLibraryCinterop/extframework/FA.framework/Headers/AAA.h
libraryPaths = xxx/TestLocalLibraryCinterop/extframework/
staticLibraries = FA.framework FB.framework
复制

cocoapods {
summary = "Some description for the Shared Module"
homepage = "https://xxxx.com/xxxx"
version = "1.0"
ios.deploymentTarget = "13.0"
framework {
baseName = "shared"
}
specRepos {
url("https://github.com/hxxyyangyong/yyspec.git")
}
pod("yytestpod"){
version = "0.1.11"
}
useLibraries()
}
复制
gradle.taskGraph.whenReady {
tasks.filter { it.name.startsWith("generateDef") }
.forEach {
tasks.named<org.jetbrains.kotlin.gradle.tasks.DefFileTask>(it.name).configure {
doLast {
val taskSuffix = this.name.replace("generateDef", "", false)
val headers = when (taskSuffix) {
"Yytestpod" -> "TTDemo.h DebugLibrary.h NSString+librarykmm.h TTDemo+kmm.h NSString+kmm.h"
else -> ""
}
val compilerOpts = when (taskSuffix) {
"Yytestpod" -> "compilerOpts = -I${buildDir}/cocoapods/synthetic/IOS/Pods/yytestpod/yytestpod/Classes/DebugFramework.framework/Headers -I${buildDir}/cocoapods/synthetic/IOS/Pods/yytestpod/yytestpod/Classes/library/include/DebugLibrary\n"
else -> ""
}
outputFile.writeText(
"""
language = Objective-C
headers = $headers
$compilerOpts
""".trimIndent()
)
}
}
}
}
复制


``` kotlin
import cocoapods.yytestpod.TTDemo
class IosGreeting {
fun calctTwoDate() {
println("Test1:" + TTDemo.callTTDemoCategoryMethod())
}
}
```
复制
publishing {
repositories {
maven {
credentials {
username = "username"
password = "password"
}
url = uri("http://maven.xxx.com/aaa/yy")
}
}
}
复制

val iosX64Main by getting {
dependencies{
implementation("groupId:artifactId:iosx64-version:cinterop-packagename@klib")
}
}
val iosArm64Main by getting {
dependencies{
implementation("groupId:artifactId:iosarm64-version:cinterop-packagename@klib")
}
}
复制
pre: 主要做一些环境的check操作 build: 执行KMM工程的build test: 执行KMM工程中的UT upload: 上传UT的报告(手动执行) deploy: 发布最终的集成产物(手动执行)

sudo curl --output usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-amd64
sudo chmod +x usr/local/bin/gitlab-runner
cd ~
gitlab-runner install
gitlab-runner start
复制
sudo gitlab-runner register --url http://xxx.com/ --registration-token xxx_token
复制
1. Enter tags for the runner (comma-separated):yy-runner
此处需要填写tag,后续设置yaml的tags需要保持一致
2. Enter an executor: instance, kubernetes, docker-ssh, parallels, shell, docker-ssh+machine, docker+machine, custom, docker, ssh, virtualbox:shell
此处我们只需要shell即可
复制



buildKMM:
stage: build
tags:
- yy-runner
script:
- sh ci/createlocalfile.sh
- ./gradlew shared:build
- cp -r -f shared/build/fat-framework/release/ ../tempframework
复制
#!/bin/sh
scriptDir=$(cd "$(dirname "$0")"; pwd)
echo $scriptDir
cd ~
rootpath=$(echo `pwd`)
cd "$scriptDir/.."
touch local.properties
echo "sdk.dir=$rootpath/Library/Android/sdk" > local.properties
复制
stage: test
tags:
- yy-runner
script:
- ./gradlew shared:iosX64Test
- rm -rf ../reporttemp
- mkdir ../reporttemp
- cp -r -f shared/build/reports/ ../reporttemp/${CI_PIPELINE_ID}_${CI_JOB_STARTED_AT}
复制
plugins {
`kotlin-dsl`
}
repositories {
jcenter()
}
复制
open class SimulatorTestsTask: DefaultTask() {
@InputFile
val testExecutable = project.objects.fileProperty()
@Input
val simulatorId = project.objects.property(String::class.java)
@TaskAction
fun runTests() {
val device = simulatorId.get()
val bootResult = project.exec { commandLine("xcrun", "simctl", "boot", device) }
try {
print(testExecutable.get())
val spawnResult = project.exec { commandLine("xcrun", "simctl", "spawn", device, testExecutable.get()) }
spawnResult.assertNormalExitValue()
} finally {
if (bootResult.exitValue == 0) {
project.exec { commandLine("xcrun", "simctl", "shutdown", device) }
}
}
}
}
```
复制
kotlin{
...
val testBinary = targets.getByName<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget>("iosX64").binaries.getTest("DEBUG")
val runIosTests by project.tasks.creating(SimulatorTestsTask::class) {
dependsOn(testBinary.linkTask)
testExecutable.set(testBinary.outputFile)
simulatorId.set(deviceName)
}
tasks["check"].dependsOn(runIosTests)
...
}
复制
val customIosTest by tasks.creating(Sync::class)
group = "custom"
val (deviceName,deviceUDID) = SimulatorHelp.getDeviceNameAndId()
kotlin.targets.withType(org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithSimulatorTests::class.java) {
testRuns["test"].deviceId = deviceUDID
}
val testBinary = kotlin.targets.getByName<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget>("iosX64").binaries.getTest("DEBUG")
val runIosTests by project.tasks.creating(SimulatorTestsTask::class) {
dependsOn(testBinary.linkTask)
testExecutable.set(testBinary.outputFile)
simulatorId.set(deviceName)
}
复制
val testBinary = targets.getByName<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget>("iosX64").binaries.getTest("DEBUG")
复制
xcrun simctl list runtimes --json
xcrun simctl list devices --json
复制
val (deviceName,deviceUDID) = SimulatorHelp.getDeviceNameAndId()
targets.withType(org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithSimulatorTests::class.java) {
testRuns["test"].deviceId = deviceUDID
}
复制

pages:
stage: build
script:
- yum -y install git
- git status
artifacts:
paths:
- public
only:
refs:
- branches
changes:
- public/index.html
tags:
- official
复制




pods源代码仓库,用于管理每次上传的framework产物,做版本控制。
podspec仓库,管理通过pods源码仓库中的spec的版本
拉取pods源码仓库,替换framework 修改pods源码仓库中的spec文件的version字段 提交修改文件,给pods仓库打上tag,和2中的version一致 将.podspec文件push到spec-repo


linkerOpts("-framework", "XXXFramework","-F${XXXFrameworkPath}")//.framework
复制
linkerOpts("-L${LibraryPath}","-lXXXLibrary")//.a
复制
kotlin {
...
targets.withType<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget> {
binaries.all {
linkerOpts("-ObjC")
}
}
...
}
复制
binaries{
getTest(org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType.DEBUG).apply{
linkerOpts("-ObjC")
}
}
复制

getTest(org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType.DEBUG).apply {
linkerOpts("-L/usr/lib/swift")
linkerOpts("-rpath","/usr/lib/swift")
linkerOpts("-L/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/${platform}")
linkerOpts("-rpath","/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/${platform}")
}
复制

“携程技术”公众号
分享,交流,成长
文章转载自携程技术,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
【干货】磐维数据库-磐维删除分区数据测试
磐维数据库
50次阅读
2025-04-24 19:53:42
Oracle GoldenGate实现数据库同步
luyingjun
45次阅读
2025-03-30 23:25:52
oracle11g迁移步骤win2008
PureSoybean
37次阅读
2025-03-28 12:13:25
cluster、update、delete在死元组清理上的作用
necessary
33次阅读
2025-04-12 14:55:38
oracle数据库导入导出命令!
淡定
33次阅读
2025-04-04 18:22:14
iOS开发数据库篇—SQL
淡定
31次阅读
2025-04-01 21:06:31
从菜鸟到大神!数据库管理员必会的Linux命令全攻略
青年数据库学习互助会
30次阅读
2025-03-31 10:02:59
MySQL NULL 值处理
张静懿
28次阅读
2025-04-08 19:11:42
《从混乱到有序:ArkUI项目文件结构改造指南》
程序员阿伟
14次阅读
2025-04-24 16:00:11
【PGCCC】Postgres 故障排除:修复重复的主键行#PostgreSQL认证
PostgreSQL培训考试认证中心
9次阅读
2025-04-23 09:52:59