Kotlin Multiplatform - Objective-C 互操作性架构问题架构的未定义符号 x86_64
Kotlin Multiplatform - Objective-C interoperability architecture issue Undefined symbols for architecture x86_64
我刚刚尝试使用本机互操作功能,因为我需要用 Objective-C 编写的本机代码才能在我的库中使用。
所以首先我尝试使用简单的 hello 来互操作 Objective-C code
gradle :
kotlin {
...
val iosX64 = iosX64("ios") {
compilations.getByName("main) {
val myInterop by cinterops.creating {
defFile(project.file("src/nativeInterop/cinterop/objective-c-file.def"))
}
}
}
val iosArm32 = iosArm32 ("iosArm32 ") {
compilations.getByName("main) {
val myInterop by cinterops.creating {
defFile(project.file("src/nativeInterop/cinterop/objective-c-file.def"))
}
}
}
val iosArm64 = iosArm64("iosArm64") {
compilations.getByName("main) {
val myInterop by cinterops.creating {
defFile(project.file("src/nativeInterop/cinterop/objective-c-file.def"))
}
}
}
...
}
我的 .def 配置:
language = Objective-C
headers = Hello.h Foundation/Foundation.h
package = org.native
compilerOpts = -Isrc/nativeInterop/include
linkerOpts = -framework Foundation "-F/Applications/Xcode 11.3.1.app/Contents/Developer/Platforms/"
这是项目结构
我的Hello.h
#import <Foundation/Foundation.h>
@interface Hello: NSObject
+ (id) init;
- (void) helloObjectiveC;
@end
Hello.m
#import "Hello.h"
@implementation Hello
+ (id) init {}
- (void) helloObjectiveC {
printf("hello Objective c interop")
}
@end
在 运行 来自 gradle 的 cinterop 任务之后,从那个 hello 生成的 klib class 当然现在我可以将它导入我的 kotlin 项目。例如在我的 iOS 模块中:
package bca.lib
import org.native.Hello
actual object Platform {
actual fun getPlatform() = "iOSMain"
fun helloNativeInterop() {
val hello = Hello()
hello.helloObjectiveC()
}
}
然后我试图在我的单元测试中调用它来检查我是否能得到结果,或者我也尝试将它构建到框架但是我得到了一个错误:
> Task :cleanIosTest UP-TO-DATE
> Task :cinteropMyInteropIos UP-TO-DATE
> Task :generateBuildKonfig UP-TO-DATE
> Task :generateIosMainAppDatabaseInterface UP-TO-DATE
> Task :compileKotlinIos UP-TO-DATE
> Task :iosProcessResources UP-TO-DATE
> Task :iosMainKlibrary UP-TO-DATE
> Task :compileTestKotlinIos UP-TO-DATE
> Task :linkDebugTestIos FAILED
e: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld invocation reported errors
Please try to disable compiler caches and rerun the build. To disable compiler caches, add the following line to the gradle.properties file in the project's root directory:
kotlin.native.cacheKind=none
Also, consider filing an issue with full Gradle log here: https://kotl.in/issue
The /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld command returned non-zero exit code: 1.
output:
Undefined symbols for architecture x86_64:
"_OBJC_CLASS_$_Hello", referenced from:
objc-class-ref in result.o
ld: symbol(s) not found for architecture x86_64
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':linkDebugTestIos'.
> Compilation finished with errors
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.6.1/userguide/command_line_interface.html#sec:command_line_warnings
BUILD FAILED in 8s
任何人都知道如何解决这个问题,或者可能无法以这种方式进行互操作?我只需要它可以在我成功构建到 .framework
之后在我的 iOS 应用程序中使用
这是一个已知限制,前一段时间在 Kotlin 问题跟踪器中有所描述:KT-39562。长话短说,cinterop
工具不提供开箱即用的源文件选项。这里最简单的方法是从您的 Objective-C 代码创建一个框架。之后,您将能够以一种简单的方式使用它,如文档中所述。
我刚刚尝试使用本机互操作功能,因为我需要用 Objective-C 编写的本机代码才能在我的库中使用。 所以首先我尝试使用简单的 hello 来互操作 Objective-C code
gradle :
kotlin {
...
val iosX64 = iosX64("ios") {
compilations.getByName("main) {
val myInterop by cinterops.creating {
defFile(project.file("src/nativeInterop/cinterop/objective-c-file.def"))
}
}
}
val iosArm32 = iosArm32 ("iosArm32 ") {
compilations.getByName("main) {
val myInterop by cinterops.creating {
defFile(project.file("src/nativeInterop/cinterop/objective-c-file.def"))
}
}
}
val iosArm64 = iosArm64("iosArm64") {
compilations.getByName("main) {
val myInterop by cinterops.creating {
defFile(project.file("src/nativeInterop/cinterop/objective-c-file.def"))
}
}
}
...
}
我的 .def 配置:
language = Objective-C
headers = Hello.h Foundation/Foundation.h
package = org.native
compilerOpts = -Isrc/nativeInterop/include
linkerOpts = -framework Foundation "-F/Applications/Xcode 11.3.1.app/Contents/Developer/Platforms/"
这是项目结构
我的Hello.h
#import <Foundation/Foundation.h>
@interface Hello: NSObject
+ (id) init;
- (void) helloObjectiveC;
@end
Hello.m
#import "Hello.h"
@implementation Hello
+ (id) init {}
- (void) helloObjectiveC {
printf("hello Objective c interop")
}
@end
在 运行 来自 gradle 的 cinterop 任务之后,从那个 hello 生成的 klib class 当然现在我可以将它导入我的 kotlin 项目。例如在我的 iOS 模块中:
package bca.lib
import org.native.Hello
actual object Platform {
actual fun getPlatform() = "iOSMain"
fun helloNativeInterop() {
val hello = Hello()
hello.helloObjectiveC()
}
}
然后我试图在我的单元测试中调用它来检查我是否能得到结果,或者我也尝试将它构建到框架但是我得到了一个错误:
> Task :cleanIosTest UP-TO-DATE
> Task :cinteropMyInteropIos UP-TO-DATE
> Task :generateBuildKonfig UP-TO-DATE
> Task :generateIosMainAppDatabaseInterface UP-TO-DATE
> Task :compileKotlinIos UP-TO-DATE
> Task :iosProcessResources UP-TO-DATE
> Task :iosMainKlibrary UP-TO-DATE
> Task :compileTestKotlinIos UP-TO-DATE
> Task :linkDebugTestIos FAILED
e: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld invocation reported errors
Please try to disable compiler caches and rerun the build. To disable compiler caches, add the following line to the gradle.properties file in the project's root directory:
kotlin.native.cacheKind=none
Also, consider filing an issue with full Gradle log here: https://kotl.in/issue
The /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld command returned non-zero exit code: 1.
output:
Undefined symbols for architecture x86_64:
"_OBJC_CLASS_$_Hello", referenced from:
objc-class-ref in result.o
ld: symbol(s) not found for architecture x86_64
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':linkDebugTestIos'.
> Compilation finished with errors
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.6.1/userguide/command_line_interface.html#sec:command_line_warnings
BUILD FAILED in 8s
任何人都知道如何解决这个问题,或者可能无法以这种方式进行互操作?我只需要它可以在我成功构建到 .framework
之后在我的 iOS 应用程序中使用这是一个已知限制,前一段时间在 Kotlin 问题跟踪器中有所描述:KT-39562。长话短说,cinterop
工具不提供开箱即用的源文件选项。这里最简单的方法是从您的 Objective-C 代码创建一个框架。之后,您将能够以一种简单的方式使用它,如文档中所述。