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 生成静态库的资料,还是参考文档

posted @ 2022-06-01 15:47  小小个子大个头  阅读(617)  评论(0编辑  收藏  举报