macOS共享库
备注
我还没有搞清楚macOS的底层库原理,这里仅记录汇总资料,有待后续学习...
我在尝试构建 darwin-jail 时候,惊奇地发现,打包提取的macOS运行环境居然高达 7.3G。这使我非常失望,如果构建一个jail环境,进而运行 Darwin Containers 需要如此巨大的footprint,那么构建类似 Docker / Kubernetes 这样的容器运行环境性价比就很低。
联想到很久以前在支付宝工作时,为线上构建线上查询日志的chroot环境,在Linux上很容易通过 ldd
找出运行程序所依赖的库文件。那么,对于 macOS ,是否有对应的工具呢?
dyld
dyld
是 动态链接编辑器
( Dynamic Link Editor
),在 macOS 和 iOS 中负责在运行时加载和链接动态库。
dyld
负责定位和加载动态框架(dynamic frameworks),程序需要dyld来运行时和链接代码需要的库。 dyld
也负责在库里面管理符号 symbols
(变量和函数的名字)并使符号对于程序可用。
在任何程序加载代码执行时, dyld
加载所有动态框架,所添加动态框架越多,则处理任务实践越长。
备注
emergetools.com 开发了一个 Emerge's performance analysis 可以分析程序加载使用的动态库框架,以及性能分析。非常类似 火焰图 ,可以辅助定位app应用性能问题。
Link fast: Improve build and launch times WWDC 2022的一个技术分享,介绍了链接静态库的原理以及苹果 ld64
的改进和如何结合参数来对程序进行瘦身和加速,以及持续改进 dyld
。
dyld-shared-cache-extrator
从 macOS Big Sur 开始,Apple 不再随 macOS 一起提供系统库,而是提供所有内置动态库的生成缓存,并排除原始库。 dyld-shared-cache-extrator 工具可以从缓存中提取这些库以进行逆向工程。
在 darwin-jail 中抽取 /System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/dyld_shared_cache_*
到jail中的 /System/Library/dyld/
就是这个原理。
dyld
库非常巨大,主要是包含了数百个库文件以及被应用加载的库的缓存(以加快启动)。 CleanMyMac 工具提供了清理 dyld
库垃圾文件的功能(我理解是清理缓存以及删除程序后不再需要的库)。
显示加载的 dylibs
dyld
提供了一个打印所有加载的 dylibs
的方法:
dyld
加载的 dylibs
export DYLD_PRINT_LIBRARIES=1
export DYLD_PRINT_RPATHS=1
export DYLD_PRINT_TO_FILE=dyld.log
myprogram
检查 dyld.log
另外 otool
可以显示程序使用的库文件,类似Linux下的 ld
。但是,这些库文件并没有实际存在于文件系统中,而是 dyld
加载的动态库(我感觉应该被加载到内存了) ,所以你实际是无法根据 otool
来打包文件的(文件不存在):
otool
显示程序使用的库otool -L /usr/bin/file
输出的使用库文件并不是存在于文件系统中
otool
显示程序使用的库输出案例/usr/bin/file:
/usr/lib/libbz2.1.0.dylib (compatibility version 1.0.0, current version 1.0.8)
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.12)
/usr/lib/liblzma.5.dylib (compatibility version 6.0.0, current version 6.3.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1351.0.0)
# 但是你直接在文件系统中是找不到该文件
% ls /usr/lib/libz.1.dylib
ls: /usr/lib/libz.1.dylib: No such file or directory