dyld 的一次报错
dyld 的一次报错
dyld: lazy symbol binding failed: Symbol not found: _objc_alloc_init
Referenced from: /Users/cz/Library/Developer/CoreSimulator/Devices/3AA8BB25-6BD7-4621-A257-F0636A0D5D09/data/Containers/Bundle/Application/0B8D3536-1FF1-4176-B818-94E44ECFC8F8/XXXXX.app/XXXXX
Expected in: /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 12.0.simruntime/Contents/Resources/RuntimeRoot/usr/lib/libobjc.A.dylib
dyld: Symbol not found: _objc_alloc_init
Referenced from: /Users/cz/Library/Developer/CoreSimulator/Devices/3AA8BB25-6BD7-4621-A257-F0636A0D5D09/data/Containers/Bundle/Application/0B8D3536-1FF1-4176-B818-94E44ECFC8F8/XXXXX.app/XXXXX
Expected in: /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 12.0.simruntime/Contents/Resources/RuntimeRoot/usr/lib/libobjc.A.dylib
CoreSimulator 757.5 - Device: iPhone X (3AA8BB25-6BD7-4621-A257-F0636A0D5D09) - Runtime: iOS 12.0 (16A366) - DeviceType: iPhone X
dyld: lazy symbol binding failed: Symbol not found: 从这个信息中也只猜是某个静态库文件的最低版本设置的有问题,比如项目是9.0 的,静态库要求 13.0 运行,那么就会出现在 iOS 13.0 以下启动闪退的问题。
为了验证这个猜想,我们需要对整个项目中的静态库进行排查,包括 pod 中的静态库
find 命令快速查找静态库文件
我们可以利用 find 命令来快速查找指定的文件
cd 代码文件夹 // 一般是工程名称,还有一个是 Pods 文件夹
find . -name "*.a"
find . -name "*.framework"
.
表示在当前目录下,你也可以跳过 cd 命令直接在指定路径下查找
-name "*.framework"
表示文件名以 .framework
结尾的所有文件
以下的部分静态库
./mob_sharesdk/ShareSDK/ShareSDK.framework
./BaiduMapKit/BaiduMapKit/BaiduMapAPI_Map.framework
查看静态库中的信息
otool -lv 路径/静态库名称 | less
otool -lv ./mob_sharesdk/ShareSDK/ShareSDK.framework/ShareSDK | less
-lv 后面一定是一个可以找到静态库的路径,如果是.a
静态库要带上后缀
| less 命令需要后续接一个 /LC_VERSION_MIN_IPHONEOS, 才能找到对应的信息,如果不带 | less,也可以自己搜索关键字 LC_VERSION_MIN_IPHONEOS
| less + /LC_VERSION_MIN_IPHONEOS 就像是帮我们做好了筛选工作
正常来说都可以看到下面信息
cmd LC_VERSION_MIN_IPHONEOS
cmdsize 16
version 8.0
sdk 11.1
Load command 3
cmd LC_DATA_IN_CODE
cmdsize 16
dataoff 582712
datasize 48
Load command 4
cmd LC_LINKER_OPTION
cmdsize 40
count 2
string #1 -framework
string #2 CoreAudio
Load command 5
cmd LC_LINKER_OPTION
cmdsize 32
count 2
string #1 -framework
string #2 CoreMIDI
Load command 6
cmd LC_LINKER_OPTION
cmdsize 40
其中 version 就是静态库限制的 iOS 最低版本
一个奇怪的库
在排查的一圈后,有个静态库确实怪怪的。使用 | less + /LC_VERSION_MIN_IPHONEOS 的方式没有返回任何信息。
去掉 | less 后,查找静态库所有信息,确实没有 LC_VERSION_MIN_IPHONEOS 相关的信息,但还有一个关键信息
Load command 1
cmd LC_BUILD_VERSION
cmdsize 24
platform IOSSIMULATOR
minos 13.0
sdk 15.4
这个是怎么回事呢?
猜测是再生产静态库时,没有指定最低版本,从而导致 Xcode 使用了默认的最低版本。
一般来说到这一步,在生成静态库的过程中,指定下最低版本即可。自行解决。
那么下一步就是去拉静态库代码,重新生成一份。在问过同事后,又得到一个不幸的消息
这个库是一个 Go 项目生成的静态库,方便 Android 和 iOS 端一起调用
感兴趣就继续看~
使用 Gomobile 生成静态库
网上最多的生成静态库命令就是这个
gomobile build [-target android|ios] [-o output] [build flags] [package]
说的是很清楚,但是没有一个实际的例子,打出来的库还是 iOS 13.0
IPHONEOS_DEPLOYMENT_TARGET
export IPHONEOS_DEPLOYMENT_TARGET=9.0
在一些论坛中和 Git 都找到了类似解决方案:
在 $GOROOT/misc/ios/clangwrap.sh 中添加这个就可以指定最低版本
事实证明不太行,或者说我没有操作对,原谅我是一个 Go 的小白
官方文档
事实证明,有些东西还真的是只能看文档,尤其是中英文博客都不太行的时候。在文档中有句话,很关键
Flag -iosversion sets the minimal version of the iOS SDK to compile against. The default version is 13.0
那么就是加个 -iosversion
gomobile build -target=ios -version=9.0 [package]
更多关于使用 gomobile 生成静态库的资料,还是参考文档吧