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

Tre*_*ies 196 c c++ unix macos

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

我有些问题:

  • 在概念层面,.so和.dylib之间的主要区别是什么?
  • 什么时候可以/我应该使用一个而不是另一个?
  • 编译技巧和提示(例如,替换gcc -shared -fPIC,因为这不适用于osx)

Mil*_*les 186

Mac OS X用于可执行文件和库的Mach-O目标文件格式区分共享库动态加载的模块.用otool -hv some_file看的文件类型some_file.

Mach-O共享库具有文件类型MH_DYLIB并带有扩展名.dylib.它们可以与通常的静态链接器标志链接,例如-lfoolibfoo.dylib.可以通过将-dynamiclib标志传递给编译器来创建它们.(-fPIC是默认值,无需指定.)

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

既dylibs和软件包可以使用动态加载dl的API(例如dlopen,dlclose).无法链接捆绑包,就像它们是共享库一样.但是,捆绑包可能与真实的共享库相关联; 这些将在加载包时自动加载.

从历史上看,差异更为显着.在Mac OS X 10.0中,无法动态加载库.一组使dyld的API(例如NSCreateObjectFileImageFromFile,NSLinkModule)与10.1介绍装载和卸载捆绑,但他们并没有对dylibs工作.dlopen10.3中添加了一个与bundle一起使用的兼容性库; 在10.4中,dlopen被重写为dyld的原生部分,并添加了对加载(但不是卸载)dylib的支持.最后,10.5添加了对使用dlclosedylibs的支持,并弃用了dyld API.

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

最后,要知道,在Mac OS X中,"捆绑"可以指向目录与持有可执行代码和代码使用的资源的标准化结构.存在一些概念上的重叠(特别是对于像插件这样的"可加载包",它通常包含Mach-O包形式的可执行代码),但它们不应与上面讨论的Mach-O包混淆.

其他参考:

  • @noloader:`-dynamiclib`是一个GCC标志.它使编译器将`-dylib`传递给ld. (4认同)
  • 感谢您的广泛评论:)我是否理解正确,如果我从另一个捆绑包加载一个捆绑包(即路径是应用程序 - >捆绑包A - >捆绑包B),那么捆绑包B将看不到任何捆绑 A 中的符号?如果是的话,有什么方法可以解决这个问题吗?我刚刚击中了它,我想:http://stackoverflow.com/questions/4193539/dynamic-symbol-lookup-fails-with-statically-embedded-python-on-mac-os-x (2认同)

Mar*_*ork 19

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

它恰好是一个普通的.

检查ArnaudRecipes sharedlib页面上的第 3b行

基本上.dylib是用于指示共享库的mac文件扩展名.

  • @ninefingers.正确.但是有些工具将使用默认值,除非某些内容非常明确.例如,当使用-l <lib>标志时,编译器将使用平台特定的共享libray扩展(实际标志可能非常跨编译器). (9认同)

Zac*_*aus 11

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
Run Code Online (Sandbox Code Playgroud)

两者在Mac OS X上等效的原因是为了与编译为.so文件类型的其他UNIX OS程序向后兼容.

编译说明:无论是编译.so文件还是.dylib文件,都需要在链接步骤中将正确的路径插入动态库中.您可以通过添加-install_name和链接命令的文件路径来完成此操作.如果你不这样做,你将遇到这篇文章中看到的问题:Mac动态图书馆疯狂(可能只是Fortran).


小智 11

只是我在使用 cmake 在 OSX 上构建原始代码时所做的观察:

cmake ... -DBUILD_SHARED_LIBS=OFF ...
Run Code Online (Sandbox Code Playgroud)

创建.so文件

尽管

cmake ... -DBUILD_SHARED_LIBS=ON ...
Run Code Online (Sandbox Code Playgroud)

创建.dynlib文件。

也许这对任何人都有帮助。