【发布时间】:2011-01-21 07:59:31
【问题描述】:
.dylib 是 macOS 上的动态库扩展,但我一直不清楚我什么时候不能/不应该使用传统的 unix .so 共享对象。
我的一些问题:
- 在概念层面上,.so 和 .dylib 之间的主要区别是什么?
- 我什么时候可以/应该使用其中一种?
- 编译技巧和提示(例如,替换 gcc -shared -fPIC,因为这在 osx 上不起作用)
【问题讨论】:
.dylib 是 macOS 上的动态库扩展,但我一直不清楚我什么时候不能/不应该使用传统的 unix .so 共享对象。
我的一些问题:
【问题讨论】:
Mac OS X 用于可执行文件和库的 Mach-O 目标文件格式区分共享库和动态加载的模块。使用otool -hv some_file查看some_file的文件类型。
Mach-O 共享库的文件类型为 MH_DYLIB,并带有扩展名 .dylib。它们可以与通常的静态链接器标志链接,例如-lfoo 用于 libfoo.dylib。它们可以通过将-dynamiclib 标志传递给编译器来创建。 (-fPIC 为默认值,无需指定。)
可加载模块在 Mach-O 语言中称为“捆绑包”。它们的文件类型为 MH_BUNDLE。他们可以进行任何扩展;扩展名.bundle 是Apple 推荐的,但大多数移植软件出于兼容性考虑使用.so。通常,您会为扩展应用程序的插件 使用捆绑包;在这种情况下,捆绑包将链接到应用程序二进制文件以访问应用程序的导出 API。它们可以通过将-bundle 标志传递给编译器来创建。
dylib 和 bundle 都可以使用dl API(例如dlopen、dlclose)动态加载。无法像共享库一样链接捆绑包。但是,捆绑包可能链接到真正的共享库。这些将在加载包时自动加载。
从历史上看,差异更为显着。在 Mac OS X 10.0 中,无法动态加载库。 10.1 引入了一组 dyld API(例如NSCreateObjectFileImageFromFile、NSLinkModule)来加载和卸载包,但它们不适用于 dylib。在 10.3 中添加了与捆绑包一起使用的 dlopen 兼容性库;在 10.4 中,dlopen 被重写为 dyld 的本机部分,并添加了对加载(但不卸载)dylib 的支持。最后,10.5 添加了对使用 dlclose 和 dylib 的支持,并弃用了 dyld API。
在 Linux 等 ELF 系统上,both use the same file format;任何一段共享代码都可以用作库和动态加载。
最后,请注意,在 Mac OS X 中,"bundle"也可以引用具有标准化结构的目录,该结构包含可执行代码和该代码使用的资源。存在一些概念上的重叠(特别是像插件这样的“可加载包”,它们通常包含 Mach-O 包形式的可执行代码),但不应将它们与上面讨论的 Mach-O 包混淆。
其他参考:
【讨论】:
-dynamiclib 是一个 GCC 标志。它使编译器将-dylib 传递给ld。
.so 文件不是共享库的 UNIX 文件扩展名。
这只是一个普通的。
检查ArnaudRecipes sharedlib page的第3b行
基本上 .dylib 是用于表示共享库的 mac 文件扩展名。
【讨论】:
mac os x 上 .dylib 和 .so 的区别在于它们的编译方式。对于 .so 文件,您使用 -shared,对于 .dylib,您使用 -dynamiclib。 .so 和 .dylib 都可以作为动态库文件互换,并且具有 DYLIB 或 BUNDLE 类型。以下是显示此内容的不同文件的读数。
libtriangle.dylib:
Mach header
magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
MH_MAGIC_64 X86_64 ALL 0x00 DYLIB 17 1368 NOUNDEFS DYLDLINK TWOLEVEL NO_REEXPORTED_DYLIBS
libtriangle.so:
Mach header
magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
MH_MAGIC_64 X86_64 ALL 0x00 DYLIB 17 1256 NOUNDEFS DYLDLINK TWOLEVEL NO_REEXPORTED_DYLIBS
triangle.so:
Mach header
magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
MH_MAGIC_64 X86_64 ALL 0x00 BUNDLE 16 1696 NOUNDEFS DYLDLINK TWOLEVEL
两者在 Mac OS X 上等价的原因是为了向后兼容其他编译为 .so 文件类型的 UNIX OS 程序。
编译注意事项:无论是编译.so 文件还是.dylib 文件,都需要在链接步骤中将正确的路径插入到动态库中。您可以通过将 -install_name 和文件路径添加到链接命令来执行此操作。如果你不这样做,你会遇到这篇文章中看到的问题:Mac Dynamic Library Craziness (May be Fortran Only)。
【讨论】:
./configure 生成.dylib 文件而不是捆绑文件.so? ./configure --enable-shared 不执行此任务。
我刚刚在 OSX 上使用 cmake 构建幼稚代码时的观察:
cmake ... -DBUILD_SHARED_LIBS=OFF ...
创建 .so 文件
同时
cmake ... -DBUILD_SHARED_LIBS=ON ...
创建 .dynlib 文件。
也许这对任何人都有帮助。
【讨论】: