Kotlin multiplatform 编译 iOS 未生成 Pods_iosApp 框架

最近玩 Kotlin multiplatform 的跨平台项目,在我从 Intel MacBook 更新到 M4 MacBook 后,居然神奇地出现无法直接在 Android Studio 中运行 iOS App 的情况。

在直接运行时,会出现如下的错误日志,提示找不到 Pods_iosApp 框架。

Ld /Users/seasonyuu/projects/BetweenUsApp/build/ios/Debug-iphonesimulator/iosApp.app/iosApp.debug.dylib normal (in target 'iosApp' from project 'iosApp')
    cd /Users/seasonyuu/projects/BetweenUsApp/iosApp
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -Xlinker -reproducible -target arm64-apple-ios16.0-simulator -dynamiclib -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator18.1.sdk -O0 -L/Users/seasonyuu/projects/BetweenUsApp/build/ios/EagerLinkingTBDs/Debug-iphonesimulator -L/Users/seasonyuu/projects/BetweenUsApp/build/ios/Debug-iphonesimulator -F/Users/seasonyuu/projects/BetweenUsApp/build/ios/EagerLinkingTBDs/Debug-iphonesimulator -F/Users/seasonyuu/projects/BetweenUsApp/build/ios/Debug-iphonesimulator -F/Users/seasonyuu/projects/BetweenUsApp/iosApp/Pods/../../shared/build/cocoapods/framework -filelist /Users/seasonyuu/projects/BetweenUsApp/build/ios/iosApp.build/Debug-iphonesimulator/iosApp.build/Objects-normal/arm64/iosApp.LinkFileList -install_name @rpath/iosApp.debug.dylib -Xlinker -rpath -Xlinker @executable_path/Frameworks -Xlinker -rpath -Xlinker @loader_path/Frameworks -dead_strip -Xlinker -object_path_lto -Xlinker /Users/seasonyuu/projects/BetweenUsApp/build/ios/iosApp.build/Debug-iphonesimulator/iosApp.build/Objects-normal/arm64/iosApp_lto.o -Xlinker -export_dynamic -Xlinker -no_deduplicate -Xlinker -objc_abi_version -Xlinker 2 -fobjc-link-runtime -L/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphonesimulator -L/usr/lib/swift -Xlinker -add_ast_path -Xlinker /Users/seasonyuu/projects/BetweenUsApp/build/ios/iosApp.build/Debug-iphonesimulator/iosApp.build/Objects-normal/arm64/iosApp.swiftmodule -ObjC -lc++ -framework shared -Xlinker -alias -Xlinker _main -Xlinker ___debug_main_executable_dylib_entry_point -framework Pods_iosApp -Xlinker -no_adhoc_codesign -Xlinker -dependency_info -Xlinker /Users/seasonyuu/projects/BetweenUsApp/build/ios/iosApp.build/Debug-iphonesimulator/iosApp.build/Objects-normal/arm64/iosApp_dependency_info.dat -o /Users/seasonyuu/projects/BetweenUsApp/build/ios/Debug-iphonesimulator/iosApp.app/iosApp.debug.dylib
ld: framework 'Pods_iosApp' not found
clang: error: linker command failed with exit code 1 (use -v to see invocation)

而这一项目此前在 Intel MacBook 下完全是可以正常编译的。

作为对比,我又创建了两个全新的项目模板,都是同时选择 Android 与 iOS,其中一个使用 cocoapods gradle 插件(IDE 直接创建并选用 cocoapods),另一个在 shared 模块中使用 compose 共享 UI(https://github.com/Kotlin/KMP-App-Template),两者都可以完全正常运行的。

对比使用 cocoapods gradle 插件的两个项目工作目录,可以发现构建过程中会去 build/ios/Debugiphonesimulator (以模拟器为 target 时)目前下去查找所需的 Framework,而全新的项目中在这一目录下会额外多出 Pods_iosApp.frameworkshared 目录,这正是编译报错的项目所缺少的关键内容。

更出奇的一点是,当使用 Xcode 去打开 iosApp.xcworkspace 来运行 iosApp 时,竟然是可以编译成功并运行到模拟器上的。

那么我从 Xcode 运行成功后,在 Xcode 中选择 Product -> Show Build Folder in Finder ,此时就可以看到与 build/ios/Debugiphonesimulator 中几近相同的目录结构,并且其中正包含 gradle 编译时所却少的 framework 目录,此时将缺少的目录复制到 build/ios/Debugiphonesimulator 中,再尝试 Android Studio 中的运行 iosApp ,则可以运行成功。

至此,我们可以推测,在生成 framework 的步骤中,Xcode 可以成功执行,但是 gradle 编译过程可能并未输出成功,抑或是输出到了错误的目录中。

上述对比过程中,作为对比的初始模板并不完全与我项目中的一致,因为我在项目中使用 shared compose ui 并且引入了 cocoapods 插件。于是我猜想是否可能是这二者的结合导致的。那么我在 KMP-App-Template 尝试加入 cocoapods 插件。

BOOM!

一模一样的错误,并且同样在 Xcode 直接运行也是可行的。

Ld /Users/seasonyuu/projects/KMP-App-Template/build/ios/Debug-iphonesimulator/KMP\ App.app/KMP\ App.debug.dylib normal (in target 'iosApp' from project 'iosApp')
    cd /Users/seasonyuu/projects/KMP-App-Template/iosApp
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -Xlinker -reproducible -target arm64-apple-ios15.3-simulator -dynamiclib -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator18.1.sdk -O0 -L/Users/seasonyuu/projects/KMP-App-Template/build/ios/EagerLinkingTBDs/Debug-iphonesimulator -L/Users/seasonyuu/projects/KMP-App-Template/build/ios/Debug-iphonesimulator -F/Users/seasonyuu/projects/KMP-App-Template/build/ios/EagerLinkingTBDs/Debug-iphonesimulator -F/Users/seasonyuu/projects/KMP-App-Template/build/ios/Debug-iphonesimulator -F/Users/seasonyuu/projects/KMP-App-Template/iosApp/Pods/../../composeApp/build/cocoapods/framework -F/Users/seasonyuu/projects/KMP-App-Template/iosApp/../shared/build/xcode-frameworks/Debug/iphonesimulator18.1 -F/Users/seasonyuu/projects/KMP-App-Template/iosApp/../composeApp/build/xcode-frameworks/Debug/iphonesimulator18.1 -filelist /Users/seasonyuu/projects/KMP-App-Template/build/ios/iosApp.build/Debug-iphonesimulator/iosApp.build/Objects-normal/arm64/KMP\ App.LinkFileList -install_name @rpath/KMP\ App.debug.dylib -Xlinker -rpath -Xlinker @executable_path/Frameworks -Xlinker -rpath -Xlinker @loader_path/Frameworks -dead_strip -Xlinker -object_path_lto -Xlinker /Users/seasonyuu/projects/KMP-App-Template/build/ios/iosApp.build/Debug-iphonesimulator/iosApp.build/Objects-normal/arm64/KMP\ App_lto.o -Xlinker -export_dynamic -Xlinker -no_deduplicate -Xlinker -objc_abi_version -Xlinker 2 -fobjc-link-runtime -L/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphonesimulator -L/usr/lib/swift -Xlinker -add_ast_path -Xlinker /Users/seasonyuu/projects/KMP-App-Template/build/ios/iosApp.build/Debug-iphonesimulator/iosApp.build/Objects-normal/arm64/KMP_App.swiftmodule -ObjC -lc++ -framework ComposeApp -Xlinker -alias -Xlinker _main -Xlinker ___debug_main_executable_dylib_entry_point -framework Pods_iosApp -Xlinker -no_adhoc_codesign -Xlinker -dependency_info -Xlinker /Users/seasonyuu/projects/KMP-App-Template/build/ios/iosApp.build/Debug-iphonesimulator/iosApp.build/Objects-normal/arm64/KMP\ App_dependency_info.dat -o /Users/seasonyuu/projects/KMP-App-Template/build/ios/Debug-iphonesimulator/KMP\ App.app/KMP\ App.debug.dylib
ld: warning: search path '/Users/seasonyuu/projects/KMP-App-Template/iosApp/../shared/build/xcode-frameworks/Debug/iphonesimulator18.1' not found
ld: framework 'Pods_iosApp' not found
clang: error: linker command failed with exit code 1 (use -v to see invocation)

那么此时可以认为,生成 Pods_iosApp.framework 是一个不论通过 gradle 编译还是 Xcode 编译都会完成的行为,只是定义输出路径不同。

To be continue

chevron_left

Leave a comment

您的邮箱地址不会被公开。 必填项已用 * 标注

Comment
Name
Email
Website