iOS高手

[iOS]Xcode "dyld: Symbol not fou

2019-11-17  本文已影响0人  pingpong_龘

1. 背景

之前电脑安装了Xcode10.1和Xcode10.2, 昨晚自动更新了Xcode11.2.

2. 现象描述

Xcode11.2更新好之后,正常跳出来同意协议:

xcode-协议-同意-image-20191115154136718.png

这有什么好犹豫的,直接无脑“Agree”,然后跳出来输入root用户的密码,输完之后,本想着进入下一步,直接安装,进度条什么的跳出来才对。

结果,

毫无反应!!!

此刻,这个协议还定在这里,这时候再点击"Agree", 连输入密码都不跳了, 一切无响应时代...

然后,如果重试几次,还是如此,甚至包括重启大招

这下就尴尬了,Xcode安装不了, 所以iOS的项目代码都没法查看了。

3. 初步尝试

3.1 google问题: xcode+license

https://www.711xd.com/p/resolve-xcode-block-at-xcode-and-ios-sdk-license-aggrement-dialog/

首先搜到这个答案,尝试了下,并没有成功,而且直接报错:

输入:

sudo xcodebuild -license

返回:

dyld: Symbol not found: _$s15_ObjectiveCTypes01_A11CBridgeablePTl
  Referenced from: /Applications/Xcode.app/Contents/Developer/usr/bin/../../../SharedFrameworks/DVTFoundation.framework/Versions/A/DVTFoundation
  Expected in: /Applications/Xcode.app/Contents/Developer/usr/bin/../../../Frameworks/libswiftCore.dylib
 in /Applications/Xcode.app/Contents/Developer/usr/bin/../../../SharedFrameworks/DVTFoundation.framework/Versions/A/DVTFoundation
Abort trap: 6

看到这个报错,一脸懵逼...

3.1 安装command-line

但想了下,我输入xcodebuild报错,有没有可能是命令行的问题。于是重新下载了最新的command-line,进行安装。

这里需要注意的是苹果已经很久之前就取消了在terminal安装command-line,需要去他的官网下载.

但是装完,发现问题依旧存在。

3.2 重新安装Xcode

这条路也是比较常见的解决方案,但一直到我开始折腾这个东西,到最终解决,这个半天时间,其实也一直再准备这个方案,奈何.... Xcode太大了,8G,我下载了几个小时都没下完(期间吃饭的时候,还中断了一次)

...

4. 开启疯狂搜索

以上几部搜索+尝试都失败之后,开始发挥程序员的search功底。 遍历google+百度,搜索了所有:

xcode | xcode11 | "dyld: Symbol not found" | "_$s15_ObjectiveCTypes01_A11CBridgeablePTl"

等相关的关键字,基本是遍历了各大技术网站,尤其是stackoverflow和github。
隐约可以看到一些提问和讨论:

https://github.com/Subito-it/sbtuitestbrowser/issues/6
https://github.com/realm/SwiftLint/issues/2736
https://github.com/Flash3001/Xamarin.Swift/issues/30
https://stackoverflow.com/questions/24043532/dyld-symbol-not-found-nsurlauthenticationmethodclientcertificate-when-trying

这个显然不对口我的问题,我这边xcode都没安装成功,更别说是项目framework了

这个command-line的方式,我之前已经尝试了,失败!

这个是建议最多的方案,查看了我xcode路径,就是/Applications/Xcode.app/Contents/Developer,没有问题。这里有个小插曲是,我命令行直接输 swift 也会报错:

dyld: Symbol not found: _$s15_ObjectiveCTypes01_A11CBridgeablePTl
  Referenced from: /Applications/Xcode.app/Contents/Developer/usr/bin/../../../SharedFrameworks/DVTFoundation.framework/Versions/A/DVTFoundation
  Expected in: /Applications/Xcode.app/Contents/Developer/usr/bin/../../../Frameworks/libswiftCore.dylib
 in /Applications/Xcode.app/Contents/Developer/usr/bin/../../../SharedFrameworks/DVTFoundation.framework/Versions/A/DVTFoundation
swift: error: unable to locate xcodebuild, please make sure the path to the Xcode folder is set correctly!
swift: error: You can set the path to the Xcode folder using /usr/bin/xcode-select -switch

比之前的报错,还是多了 2行,然后尝试修改xcode路径:sudo xcode-select --switch /Library/Developer/CommandLineTools/,从Xcode.app改成CommandLineTools之后,swift反倒是正常了。输入swift,提示

Welcome to Apple Swift version 5.1.2 (swiftlang-1100.0.278 clang-1100.0.33.9).

但这个指标不治本,所以后面还是改为sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer

总而言之,没有一个能解决我的问题。

5. 重新思考

现在感觉就是遇到了一个难题,而平时万能的stackoverflow 也没有给出答案的时候,只能静下心来,重新思考,靠自己解决了。

那我们重新回过头审视这个问题:

dyld: Symbol not found: _$s15_ObjectiveCTypes01_A11CBridgeablePTl

这个是比较常见的Symbol not found,这一类问题可以搜出来很多,但每个具体找不到的不一样。

这里是s15_ObjectiveCTypes01_A11CBridgeablePTl.看名猜想应该是ObjeciveCType相关的一个桥接文件或者函数。

无意搜到ObjectiveCTypes.swift, 来自于/linux/misc/swift-swift-5.1.2-RELEASE.tar.gz , 是swift5的一个文件。

然后继续看错误提示:

Referenced from: /Applications/Xcode.app/Contents/Developer/usr/bin/../../../SharedFrameworks/DVTFoundation.framework/Versions/A/DVTFoundation
Expected in: /Applications/Xcode.app/Contents/Developer/usr/bin/../../../Frameworks/libswiftCore.dylib
in /Applications/Xcode.app/Contents/Developer/usr/bin/../../../SharedFrameworks/DVTFoundation.framework/Versions/A/DVTFoundation

其实仔细看,问题提示还是很明显,DVTFoundation 文件中引用了s15_ObjectiveCTypes01_A11CBridgeablePTl, 在/Applications/Xcode.app/Contents/Developer/usr/bin/../../../Frameworks/路径下的libswiftCore.dylib的文件中找不到。

于是去查看了这个libswiftCore.dylib

xcode-app-libswift的路径-4.2.1-image-20191115233032801.png

突然看到他的版本是4.2.1,联想到之前查stackoverflow的时候,有部分人谈及swift5和swift4版本的问题,又想到前面搜ObjectiveCTypes.swift是swift5的一个文件。

那基本怀疑是这个libswiftCore.dylib是旧版本的,升级到swift5的版本就好了。

6. 尝试解决问题

6.1 解决Xcode的"dyld: Symbol not found"

那下面的问题是如何把xcode的frameworks文件的swiftlib文件升级到swift5. 那最简单的方式是找到swift5版本的libswiftCore.dylib替换即可。

但有一个顾虑就是:因为上下的文件都扫了几眼,这个Frameworks目录下swift相关的lib文件都是4.2.1,彼此之间可能会有依赖,不确定只替换一个是否可行,更严谨的方案是相关文件都批量替换掉。

那问题转化成:如何批量升级libswift相关文件

想到的方案是官方搜xcode的framework文件夹或者libswiftCore.dylib系列库,

可不知道是渠道不对还是打开方式不对,搜了半天也没搜到。且不说搜到xcode对应的framework的系列版本,单个libswiftCore也没搜到。

那换个思路想,之所以出现这个问题,我电脑之前同时安装了xcode10.1和xcode10.2版本,现在自动升级后,2个xcode变成了一个,是不是可能就得xcode的遗留文件没删除干净,导致遗留了旧的libswiftCore.dylib. 而macOS本身自带swift命令行,且我之前安装过iPhone的各种模拟器,那我本地电脑应该也有这个文件的啊。

于是本地开始搜索

sudo find / -name libswiftCore.dylib

解决如下:

本地搜索libswift-文件-image-20191115234549775.png

果然,搜到了一大堆,仿佛看到了曙光。

查看了下首当其冲的是:系统路径下的/usr/lib/swift/libswiftCore.dylib

系统usr路径下的swiftlib-5.0-image-20191115234852107.png

Aha,这个是5.0版本的。

左右对比了下/usr/lib/swift/ 和xcode的../Frameworks/下的swiftlib,文件重合度不高,所以无法实现全部替换xcode的全部4.2.1的swiftlib相关文件。

批量替换有难度,那就决定先只替换libswiftCore.dylib

先备份了一个4.2.1版本,之后替换了新的libswiftCore.dylib,于是尝试xcodebuild命令,立刻恢复了正常,同时庆幸没有出现其他依赖问题。

回到最开始:

sudo xcodebuild -license

不再报错:“dyld: Symbol not found”,并正常跳出协议页面。

同意协议,安装,完成,Xcode可以正常打开了。

OK, 截止目前我们遇到的问题:

这些问题全部得以解决,解决的方法,仅仅是替换libswiftCore.dylib文件

6.2 彻底解决

原本到这里可以结束了,但是当我们基于现在的环境,去build一个xcode项目时,突然又产生了一堆新问题:

按照网上的建议,删除模拟器,删除缓存,clean等一波操作之后,都没能解决。

这时候,终于意识到,前面单个替换ibswiftCore.dylib, 的确只是个治标不治本的方案,担心的问题还是来了。xcode中swift相关的库一系列都是swift4的,我只是将其中的一个标准库替换为swift5,而其他文件直接难免彼此有依赖,所以如果我不批量替换的话,永远会有数不尽的问题会等着我。

痛定思痛,还是决定重新下载一个Xcode11

...

一个小时以后,下载完成。

重新安装,并build项目文件,一切都正常了。

到此,我们再汇总一遍遇到的问题:

这些问题全部得以解决,解决的方法是:卸载重装

这么多步走下来,不容易啊...

7. 分析出现问题原因

7.1 明确基本原因

虽然问题解决了,但我们可以再反过来思考下,为什么会出现这个问题,DVTFoundation 究竟是何物?

于是用MachOView查看该文件:(DVTFoundation是mach-o文件)

mach-o-view-DVTFoundation-image-20191116064739850.png

可以看到这里引用了libSwiftCore.dylib,路径设置为@rpath表示从本地路径搜索,在编译过程中这个@rpath也支持被替换为@executable_path或者@loader_path 甚至多个路径。

本问题中,被设置的路径是:/Applications/Xcode.app/Contents/Developer/usr/bin/../../../Frameworks/

我们可以看到DVTFoundation文件其他代码使用的都是swift5的类型或者引用,显然DVTFoundation 已是基于swift5写的代码,而引用的libSwiftCore.dylib是swift4的版本,所以出现的API兼容问题。

那问题显然是比较明确的,版本兼容问题。

7.2 尝试分析源头

另外,想直接看一下libSwiftCore.dylib在swift5和swift4的区别,是不是swift5的版本多了一些类似"_$s15_ObjectiveCTypes01_A11CBridgeablePTl"的函数,当然不是全字符匹配了,挑关键字搜一下,"ObjectiveCType","CBridgeable" ...

Swift5

swift5

Swfit4

ida-swfit4-swifitcore-lib-image-20191117165231402.png

但是搜下了基本无差,说明问题的代码还没找到。

那进一步,直接看源码.
但是简单搜了一圈,还是没有找到比较直接相关的源码。

可能需要点时间,去对比swift4和swift5的diff,看看swift/objC的类型转换或者bridge相关逻辑是否有改动/更新等。

这块可以作为后续的扩展工作,等有时间去挖掘一下(如果有哪位大神了解,希望指点一二)。

补充:

  1. libSwfitCore就是swift的标准库,源码在:https://github.com/apple/swift/tree/master/stdlib/public/core
  2. 一个可以查看dylib文件的网站:https://filext.com/file-extension/DYLIB

7.3 猜测触发原因

问题是知道了,但是为什么会触发这个问题?

现在去对比重新安装的Xcode和之前自动升级的Xcode。

新下载的xcode11.2

xcode-新下载-framework路径很简单-image-20191117230427290.png

之前自动升级的xcode11.2

xcode-自动升级-framework路径很复杂-image-20191117230427290.png

发现,新下载的在路Frameworks路径下文件很少,且压根就没有swiftlibCore文件。

所以,今天的这一切,显然是个Xcode的bug:

Xcode 10.1 只支持swift4,从10.2版本开始内嵌的swift5的libswiftCore, 但我这次升级Xcode 11,里面却还是swift4的libswiftCore
他们DVTFoundation 文件 引用libSwiftCore.dylib的路径@rpath是可以在编译时设置的,
所以可以猜一下,他们@rpath的设置逻辑是:

Xcode10.1的libswiftCore 文件没有被删除,一路留了下来,最终成为了"一颗炸弹".
能一路留下来,那可能升级过程,文件/代码库采用的是Update方式而非Override方式。

总之,是一大悲剧。

另外补充一个以前的插曲:
我们自己的App中之前遇到过用Xcode10.2以后的版本打swift4的包(Build Setting中选择swift4.2),但是Xcode依旧会用swift5的libswiftCore
尽管swift5的libswiftCore这个版本是向下兼容的,所以可以打出swift4 SDK支持的包,但是swift5的NSClassFromString 会有些性能问题,导致App很多地方巨卡无比,最后不得已用Xcode10.1重新打包,才恢复正常。

8. 总结

其实今天回头再看是个很简单的问题,问题本身并没有什么复杂度可言,可能有的人遇到类似场景后,搜一搜估计几分钟就能解决。
但解决之后,可以再去复盘一下我们在解决问题的过程中的思维习惯:

上一篇下一篇

猜你喜欢

热点阅读