.so和.dylib在osx上有什么区别?

.dylib是OSX上的dynamic库扩展,但是当我不能/不应该使用传统的unix .so共享对象时,我从来没有清楚过。

我有一些问题:

  • 在概念层面,.so和.dylib之间的主要区别是什么?
  • 什么时候可以/应该使用哪一种?
  • 编译技巧和提示(例如,replacegcc -shared -fPIC,因为这在osx上不起作用)

Mac OS X用于可执行文件和库的Mach-O目标文件格式区分共享库dynamic加载的模块 。 使用otool -hv some_file来查看otool -hv some_file的文件types。

Mach-O共享库的文件types为MH_DYLIB并带有扩展名.dylib。 它们可以与通常的静态链接器标志链接起来,例如-lfoo的-lfoo。 可以通过将-dynamiclib标志传递给编译器来创build它们。 ( -fPIC是默认的,不需要指定。)

可加载模块在Mach-O中被称为“捆绑”。 他们有文件typesMH_BUNDLE 。 他们可以进行任何延期; Apple推荐扩展.bundle ,但为了兼容,大多数移植软件都使用.so 。 通常,您将使用捆绑包来扩展应用程序; 在这种情况下,捆绑软件将链接到应用程序二进制文件,以获得对应用程序导出的API的访问。 可以通过将-bundle标志传递给编译器来创build它们。

dylib和bundle都可以使用dl APIdynamic加载(例如dlopendlclose )。 就像共享库一样,不能像捆绑一样链接。 但是,一个包可能与真正的共享库链接。 这些将在加载包时自动加载。

历史上,差异更为显着。 在Mac OS X 10.0中,无法dynamic加载库。 10.1引入了一套dyld API(例如NSCreateObjectFileImageFromFileNSLinkModule )来加载和卸载bundle,但是它们不适用于dylib。 在10.3中添加了一个与捆绑工作的dlopen兼容性库; 在10.4中, dlopen被改写为dyld的本地部分,并增加了对dylib加载(但不卸载)的支持。 最后,10.5增加了对dylib使用dlclose支持,并且弃用了dyld APIs。

在像Linux这样的ELF系统上, 两者都使用相同的文件格式 。 任何一段共享代码都可以用作库和dynamic加载。

最后,请注意,在Mac OS X中, “bundle”也可以指具有标准化结构的目录,该结构包含可执行代码和该代码使用的资源。 这里有一些概念上的重叠(特别是“可加载的包”,比如插件,通常包含Mach-O包的可执行代码),但是不应该把它与上面讨论的Mach-O包混淆起来。

其他参考:

  • 芬克移植指南 ,这个答案的基础(尽pipe相当过时,因为它是为Mac OS X 10.3编写的)。
  • ld(1)和dlopen(3)
  • dynamic库编程主题
  • Mach-O编程主题

该文件.so不是共享库的UNIX文件扩展名。

这恰好是一个常见的问题。

在ArnaudRecipes sharedlib页面查看第3b行

基本上.dylib是用来表示共享库的mac文件扩展名。

.dylib和.so在mac os x上的区别在于它们是如何编译的。 对于使用-shared的.so文件,对于.dylib使用-dynamiclib。 .so和.dylib都可以作为dynamic库文件互换,并且可以具有DYLIB或BUNDLEtypes。 下面是不同文件的显示。

 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文件types的UNIX操作系统程序。

编译注意事项:无论是编译.so文件还是编译.dylib文件,都需要在链接步骤中将正确的path插入到dynamic库中。 您可以通过添加-install_name和链接命令的文件path来执行此操作。 如果你不这样做,你会遇到这个post中看到的问题: Macdynamic图书馆的疯狂(可能只有Fortran) 。

只是我用cmake在OSX上构build朴素代码时所做的一个观察:

cmake … -DBUILD_SHARED_LIBS = OFF …

创build.so文件

cmake … -DBUILD_SHARED_LIBS = ON …

创build.dynlib文件。

也许这有助于任何人。