1. 背景
之前电脑安装了Xcode10.1和Xcode10.2, 昨晚自动更新了Xcode11.2.
2. 现象描述
Xcode11.2更新好之后,正常跳出来同意协议:
这有什么好犹豫的,直接无脑“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
- 有说是swift的frameword的问题,需要把项目framework移除再添加
这个显然不对口我的问题,我这边xcode都没安装成功,更别说是项目framework了
- 有说是swift5的问题,install一个支持swift5的command-line...
这个command-line的方式,我之前已经尝试了,失败!
- 有说xcode的路径不对,检查一下(
xcode-select -p
), 更新为正确的路径
(sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
)
这个是建议最多的方案,查看了我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
突然看到他的版本是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
解决如下:
果然,搜到了一大堆,仿佛看到了曙光。
查看了下首当其冲的是:系统路径下的/usr/lib/swift/libswiftCore.dylib
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, 截止目前我们遇到的问题:
- license点击agree无反应
- xcode无法打开
- 命令行
xcodebuild
/swift
命令报错:"dyld: Symbol not found"
这些问题全部得以解决,解决的方法,仅仅是替换libswiftCore.dylib
文件。
6.2 彻底解决
原本到这里可以结束了,但是当我们基于现在的环境,去build一个xcode项目时,突然又产生了一堆新问题:
- Swift does not support the SDK 'iPhoneSimulator11.2.sdk
- Swift does not support the SDK ‘MacOSX10.14.sdk’
- ...
按照网上的建议,删除模拟器,删除缓存,clean等一波操作之后,都没能解决。
这时候,终于意识到,前面单个替换ibswiftCore.dylib
, 的确只是个治标不治本的方案,担心的问题还是来了。xcode中swift相关的库一系列都是swift4的,我只是将其中的一个标准库替换为swift5,而其他文件直接难免彼此有依赖,所以如果我不批量替换的话,永远会有数不尽的问题会等着我。
痛定思痛,还是决定重新下载一个Xcode11
...
一个小时以后,下载完成。
重新安装,并build项目文件,一切都正常了。
到此,我们再汇总一遍遇到的问题:
- license点击agree无反应
- xcode无法打开
- 命令行
xcodebuild
/swift
命令报错:“dyld: Symbol not found” - 替换
libswiftCore.dylib
为swift5之后,编译项目报错:“Swift does not support the SDK 'iPhoneSimulator11.2.sdk” - 删除iPhoneSimulator11.2之后,报错:“Swift does not support the SDK ‘MacOSX10.14.sdk’”
这些问题全部得以解决,解决的方法是:卸载重装。
这么多步走下来,不容易啊...
7. 分析出现问题原因
7.1 明确基本原因
虽然问题解决了,但我们可以再反过来思考下,为什么会出现这个问题,DVTFoundation
究竟是何物?
于是用MachOView查看该文件:(DVTFoundation
是mach-o文件)
可以看到这里引用了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
Swfit4
但是搜下了基本无差,说明问题的代码还没找到。
那进一步,直接看源码.
但是简单搜了一圈,还是没有找到比较直接相关的源码。
可能需要点时间,去对比swift4和swift5的diff,看看swift/objC的类型转换或者bridge相关逻辑是否有改动/更新等。
这块可以作为后续的扩展工作,等有时间去挖掘一下(如果有哪位大神了解,希望指点一二)。
补充:
libSwfitCore
就是swift的标准库,源码在:https://github.com/apple/swift/tree/master/stdlib/public/core- 一个可以查看dylib文件的网站:https://filext.com/file-extension/DYLIB
7.3 猜测触发原因
问题是知道了,但是为什么会触发这个问题?
现在去对比重新安装的Xcode和之前自动升级的Xcode。
新下载的xcode11.2
之前自动升级的xcode11.2
发现,新下载的在路Frameworks路径下文件很少,且压根就没有swiftlibCore
文件。
所以,今天的这一切,显然是个Xcode的bug:
Xcode 10.1 只支持swift4,从10.2版本开始内嵌的swift5的libswiftCore
, 但我这次升级Xcode 11,里面却还是swift4的libswiftCore
。
他们DVTFoundation
文件 引用libSwiftCore.dylib
的路径@rpath是可以在编译时设置的,
所以可以猜一下,他们@rpath的设置逻辑是:
- 优先Xcode的Frameworks路径
- 如果没有,则寻找其他可执行路径(可以猜一下,可能是:对应模拟器/真机执行文件路径或者系统路径之类)
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. 总结
其实今天回头再看是个很简单的问题,问题本身并没有什么复杂度可言,可能有的人遇到类似场景后,搜一搜估计几分钟就能解决。
但解决之后,可以再去复盘一下我们在解决问题的过程中的思维习惯:
- 不要着急着打开google或者百度,或许多停下来,想一想,再看看错误描述,稍加尝试,可能就轻而易举解决了。
- stackoverflow是一剂良药,但是思考也很重要。
- 任何工程问题的本质,都是程序员的代码跑不下去了,你只需要静下来看看他哪里中断了,帮帮他就好了。
- 当然,如果实在帮不动,那就卸载重装吧。