MacOS:多架构产物如何融合?
文章目录
MacOS 和 iOS 使用多架构的 MachO 产物,称为 flat binary,本文将探索对于单架构与多架构的各种组合方式。
太长不读结论版:通常会默认以本机系统架构进行融合,如果编译器或链接器无法分析出需要融合的架构,需要指定 -target / -arch 来辅助。
本机系统架构:x86_64
本文大纲如下:
1、多架构编译
2、单架构 MachO 和 多架构库
3、多架构 MachO 和 多架构库
4、多架构 MachO 和 单架构库
5、总结
1、多架构编译
- 编译多架构
|
|
- 合并多架构
|
|
- 打包成静态库
|
|
- 打包成动态库
|
|
2、单架构 MachO 和 多架构库
- 静态库
|
|
- 动态库
|
|
用 MachOView 查看,可以看到多架构动态库 share 只有 share_x86 这个会被链接。
我们合成的多架构动态库 share 被分拆了,只拿了其中的 x86_64 的部分。
注意:这样会有什么问题?
可以看到这里 LC_LOAD_DYLIB
的路径信息 name 是相对路径,即编译器/链接器默认我们 main 执行文件,即放 share 动态库的地方会有 share_x86
这个单架构文件。
那如果找不到的话,是会报运行时错误的,所以多架构合成之后,也要小心不要把单架构文件删掉了。
其原因在于我合成的动态库其架构上的路径的不统一:
不过 iOS 开发不需要担心,Xcode 对于多架构的处理非常好:
其路径下的 name 是完全一样的,而且也没有发生像我这种拆分情况,直接链接的就是多架构的库
是我合成的动态库不标准,不同架构的路径不一样,但 Xcode 合成的路径是同一个。
比如图中的 /usr/lib/libSystem.B.dylib
它就是个多架构的库,并不影响单架构的使用。
那么 Xcode 是如何控制这个路径一样的呢?
|
|
用这个就能控制动态库的搜索路径了。
即使库是多架构,可执行文件是单架构,也不用慌,因为只有对应架构部分被加载到内存当中。
如何验证?可以试试查找多架构库其中的某一个函数,会发现只有对应架构的版本。
|
|
想想其实很合理,看看文件结构就知道了:
文件当中会有 Fat Header,记录不同架构各自的 Header 信息在哪里,然后再去处理自己所需要的那部分架构。
但如果库中没有所需要的架构,那么肯定就是报错了:
|
|
题外话:新版 Xcode 可能找不到设置架构的地方,可以用以下操作:
3、多架构 MachO 和 多架构库
|
|
多架构与多架构无法直接链接到一起,需要指定架构,分别链接好了,再合成到一起
4、多架构 MachO 和 单架构库
- x86 库
- arm64 库
由于默认是本机架构 x86_64,所以没能从中找到对应的符号,指定 arm64 架构看看:
|
|
- 动态库
可以看到多架构的 MachO 会被分拆,同样试试 arm64:
|
|
5、总结
通常会默认以本机系统架构进行融合,如果编译器或链接器无法分析出需要融合的架构,需要指定 -target / -arch 来辅助。
文章作者 calssion
上次更新 2021-05-03