macOS 上的 .so 和 .dylib 有什么区别?
.dylib 是 macOS 上的动态库扩展,但我一直不清楚什么时候我不能/不应该使用传统的 unix .so 共享对象。
我的一些问题:
- 在概念层面上,.so 和 .dylib 之间的主要区别是什么?
- 我什么时候可以/应该使用其中一种而不是另一种?
- 编译技巧&提示(例如,替换 gcc -shared -fPIC,因为它在 osx 上不起作用)
.dylib is the dynamic library extension on macOS, but it's never been clear to me when I can't / shouldn't use a traditional unix .so shared object.
Some of the questions I have:
- At a conceptual level, what are the main differences between .so and .dylib?
- When can/should I use one over the other?
- Compilation tricks & tips (For example, the replacement for gcc -shared -fPIC, since that doesn't work on osx)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Mac OS X 用于可执行文件和库的 Mach-O 目标文件格式区分共享库和动态加载模块。使用
otool -hv some_file
查看some_file
的文件类型。Mach-O 共享库的文件类型为
MH_DYLIB
并带有扩展名 .dylib。它们可以与通常的静态链接器标志链接,例如 libfoo.dylib 的-lfoo
。它们可以通过将-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 添加了对 dylib 中使用 dlclose 的支持,并弃用了 dyld API。在 Linux 等 ELF 系统上,两者都使用相同的文件格式;任何共享代码都可以用作库并用于动态加载。
最后,请注意,在 Mac OS X 中," “bundle”也指的是具有标准化结构的目录,其中包含可执行代码和该代码使用的资源。有一些概念上的重叠(特别是像插件这样的“可加载包”,它们通常包含 Mach-O 包形式的可执行代码),但它们不应该与上面讨论的 Mach-O 包混淆。
其他参考文献:
The Mach-O object file format used by Mac OS X for executables and libraries distinguishes between shared libraries and dynamically loaded modules. Use
otool -hv some_file
to see the filetype ofsome_file
.Mach-O shared libraries have the file type
MH_DYLIB
and carry the extension .dylib. They can be linked against with the usual static linker flags, e.g.-lfoo
for libfoo.dylib. They can be created by passing the-dynamiclib
flag to the compiler. (-fPIC
is the default and needn't be specified.)Loadable modules are called "bundles" in Mach-O speak. They have the file type
MH_BUNDLE
. They can carry any extension; the extension.bundle
is recommended by Apple, but most ported software uses.so
for the sake of compatibility. Typically, you'll use bundles for plug-ins that extend an application; in such situations, the bundle will link against the application binary to gain access to the application’s exported API. They can be created by passing the-bundle
flag to the compiler.Both dylibs and bundles can be dynamically loaded using the
dl
APIs (e.g.dlopen
,dlclose
). It is not possible to link against bundles as if they were shared libraries. However, it is possible that a bundle is linked against real shared libraries; those will be loaded automatically when the bundle is loaded.Historically, the differences were more significant. In Mac OS X 10.0, there was no way to dynamically load libraries. A set of dyld APIs (e.g.
NSCreateObjectFileImageFromFile
,NSLinkModule
) were introduced with 10.1 to load and unload bundles, but they didn't work for dylibs. Adlopen
compatibility library that worked with bundles was added in 10.3; in 10.4,dlopen
was rewritten to be a native part of dyld and added support for loading (but not unloading) dylibs. Finally, 10.5 added support for usingdlclose
with dylibs and deprecated the dyld APIs.On ELF systems like Linux, both use the same file format; any piece of shared code can be used as a library and for dynamic loading.
Finally, be aware that in Mac OS X, "bundle" can also refer to directories with a standardized structure that holds executable code and the resources used by that code. There is some conceptual overlap (particularly with "loadable bundles" like plugins, which generally contain executable code in the form of a Mach-O bundle), but they shouldn't be confused with Mach-O bundles discussed above.
Additional references:
Mac OS X 上的 .dylib 和 .so 之间的区别在于它们的编译方式。对于 .so 文件,您使用 -shared;对于 .dylib,您使用 -dynamiclib。 .so 和 .dylib 都可以作为动态库文件互换,并且类型均为 DYLIB 或 BUNDLE。这是显示这一点的不同文件的读数。
两者在 Mac OS X 上等效的原因是为了向后兼容编译为 .so 文件类型的其他 UNIX 操作系统程序。
编译注意事项:无论编译.so文件还是.dylib文件,都需要在链接步骤中将正确的路径插入到动态库中。您可以通过将 -install_name 和文件路径添加到链接命令来完成此操作。如果您不这样做,您将遇到本文中看到的问题:Mac 动态库疯狂(可能仅限 Fortran)。
The difference between .dylib and .so on mac os x is how they are compiled. For .so files you use -shared and for .dylib you use -dynamiclib. Both .so and .dylib are interchangeable as dynamic library files and either have a type as DYLIB or BUNDLE. Heres the readout for different files showing this.
The reason the two are equivalent on Mac OS X is for backwards compatibility with other UNIX OS programs that compile to the .so file type.
Compilation notes: whether you compile a .so file or a .dylib file you need to insert the correct path into the dynamic library during the linking step. You do this by adding -install_name and the file path to the linking command. If you dont do this you will run into the problem seen in this post: Mac Dynamic Library Craziness (May be Fortran Only).
只是我刚刚在 OSX 上使用 cmake 构建简单代码时所做的观察:
创建 .so 文件,
同时
创建 .dynlib 文件。
也许这对任何人都有帮助。
Just an observation I just made while building naive code on OSX with cmake:
creates .so files
while
creates .dynlib files.
Perhaps this helps anyone.
文件 .so 不是共享库的 UNIX 文件扩展名。
它只是碰巧是一个常见的。
检查 ArnaudRecipes sharelib 页面的第 3b 行基本上
.dylib 是 mac 文件扩展名,用于指示共享库。
The file .so is not a UNIX file extension for shared library.
It just happens to be a common one.
Check line 3b at ArnaudRecipes sharedlib page
Basically .dylib is the mac file extension used to indicate a shared lib.