MacOS:多架构产物如何融合?

本文介绍如何使用GCC和Lipo工具进行多架构编译和链接,包括单架构与多架构库的混合使用,以及多架构MachO文件的创建。特别关注不同架构下动态库和静态库的处理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本机系统架构:x86_64

太长不读总结:通常会默认以本机系统架构进行融合,如果编译器或链接器无法分析出需要融合的架构,需要指定 -target / -arch 来辅助。

1、多架构编译

  • 编译多架构
gcc -target x86_64-apple-macos10.15 -c add.c -o x86

gcc -target arm64-apple-ios9.0 \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk \
-c add.c -o arm64

image.png

  • 合并多架构
lipo -create -output add.o x86 arm64

image.png

  • 打包成静态库
ar rcs libadd.a add.o

image.png

  • 打包成动态库
gcc -target x86_64-apple-macos10.15 -fPIC add.o -shared -o share_x86

gcc -target arm64-apple-ios9.0 -fPIC add.o -shared \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk \
-o share_arm64

lipo -create -output share share_x86 share_arm64

image.png

2、单架构 MachO 和 多架构库

  • 静态库
gcc libadd.a main.c -o main

// 或者使用下面的方式,因为本质上是链接器在做融合
gcc -c main.c -o main.o
ld main.o libadd.a -lSystem -o main

image.png

  • 动态库
ld main.o share -lSystem -o main

image.png

image.png

用 MachOView 查看,可以看到多架构动态库 share 只有 share_x86 这个会被链接。

我们合成的多架构动态库 share 被分拆了,只拿了其中的 x86_64 的部分。

注意:这样会有什么问题?

可以看到这里 LC_LOAD_DYLIB 的路径信息 name 是相对路径,即编译器/链接器默认我们 main 执行文件,即放 share 动态库的地方会有 share_x86 这个单架构文件。

那如果找不到的话,是会报运行时错误的,所以多架构合成之后,也要小心不要把单架构文件删掉了。

image.png

其原因在于我合成的动态库其架构上的路径的不统一:

image.png

image.png

不过 iOS 开发不需要担心,Xcode 对于多架构的处理非常好:

其路径下的 name 是完全一样的,而且也没有发生像我这种拆分情况,直接链接的就是多架构的库

image.png

是我合成的动态库不标准,不同架构的路径不一样,但 Xcode 合成的路径是同一个。

比如图中的 /usr/lib/libSystem.B.dylib

image.png

image.png

image.png

它就是个多架构的库,并不影响单架构的使用。

那么 Xcode 是如何控制这个路径一样的呢?

-install_name @rpath/share

用这个就能控制动态库的搜索路径了。

即使库是多架构,可执行文件是单架构,也不用慌,因为只有对应架构部分被加载到内存当中。

如何验证?可以试试查找多架构库其中的某一个函数,会发现只有对应架构的版本。

dis -n "函数符号名"

想想其实很合理,看看文件结构就知道了:

image.png

文件当中会有 Fat Header,记录不同架构各自的 Header 信息在哪里,然后再去处理自己所需要的那部分架构。

但如果库中没有所需要的架构,那么肯定就是报错了:

dyld: Library not loaded: @rpath/XXX.framework/XXX

题外话:新版 Xcode 可能找不到设置架构的地方,可以用以下操作:

image.png

3、多架构 MachO 和 多架构库

gcc -target x86_64-apple-macos10.15 -c main.c -o main_x86

gcc -target arm64-apple-ios9.0 \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk \
-c main.c -o main_arm64

lipo -create -output main.o main_x86 main_arm64

image.png

多架构与多架构无法直接链接到一起,需要指定架构,分别链接好了,再合成到一起

image.png

4、多架构 MachO 和 单架构库

  • x86 库

image.png

  • arm64 库

image.png

由于默认是本机架构 x86_64,所以没能从中找到对应的符号,指定 arm64 架构看看:

gcc -target arm64-apple-ios9.0 \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk \
main.o arm64 -o main

image.png

  • 动态库

image.png

可以看到多架构的 MachO 会被分拆,同样试试 arm64:

gcc -target arm64-apple-ios9.0 \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk \
main.o share_arm64 -o main

image.png

5、总结

通常会默认以本机系统架构进行融合,如果编译器或链接器无法分析出需要融合的架构,需要指定 -target / -arch 来辅助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值