What are the differences between .so and .dylib on macOS?
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 of some_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. A dlopen
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 using dlclose
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:
- Fink Porting Guide, the basis for this answer (though pretty out of date, as it was written for Mac OS X 10.3).
- ld(1) and dlopen(3)
- Dynamic Library Programming Topics
- Mach-O Programming Topics
macOS: What's the correct place to install a dylib on a user's system?
The Mac is a bit of a strange beast when it comes to file system locations, and it's going to get more difficult after macOS 10.15 (Catalina) ships, due to the primary boot file system being read-only.
Depending on the purpose of accessing the library, there are some appropriate places to put it.
In your Application bundle
If you have an Application that is being installed globally in the /Applications
folder (most Applications are on the Mac, but sometimes users put them in strange places), then you could use the Application's own folder for storage of the library and it would be available to any code that can read in that folder. There are a number of problems with this, though: the user can move the Application, permissions may be wrong, and you have to be careful in any code that uses the Apple Hardened Runtime because it requires special flags to load code signed by anyone other than the signatory on the Application loading the library. The advantage is that deleting the Application also deletes your library, so you don't need to write an uninstaller. This technique is used by software like VMWare Fusion (if you need to run command-line code or similar) and
/Library/Application Support or /Library/Frameworks
If you need the library to be persistent and guaranteed to be in one clearly-defined location, then having the User approve your installation into /Library/Application Support/<your application>
or into /Library/Frameworks
is likely your best bet.
/usr/local/lib
As you've already noticed, /usr/local/lib
can be problematic, especially since the popular Homebrew package manager generally sets the /usr/local/lib
to be owned by the user installing files with brew so that it can be modified without needing to sudo
.
With that said, though, you can install in /usr/local/lib
, with the proviso that you may need to escalate privileges in order to perform the installation. Once the installation is done, the directory is usually set to be readable by any other user on the system.
Recommendation
As a long-time Mac user, I prefer when Applications keep themselves contained (codewise) to their Application bundle, and thus would encourage using that mechanism. The downside of the user not installing in /Applications
can be mitigated by having the Application itself check when it runs to make sure that it's in the right place, and if not, prompt the user to move it (or do the moving after asking for a privilege elevation). This also removes the need for an installer/uninstaller program.
If that's not acceptable for some reason, then the /Library/Frameworks
or /Library/Application Support/<your application>
would be your next best bet. They're much less likely to create a problem than /usr/local/lib
.
What is the difference between .dylib and .a lib in ios?
Static Library(.a)
Static libraries allow an application to load code into its address space at compile time.This results in a larger size on disk and slower launch times. Because the library's code is added directly to the linked target's binary, it means that to update any code in the library, the linked target would also have to be rebuilt.
Dynamic Library(.dylib)
Dynamic libraries allow an application to load code into its address space when it’s actually needed at run time. Because the code isn't statically linked into the executable binary, there are some benefits from loading at runtime. Mainly, the libraries can be updated with new features or bug-fixes without having to recompile and relink executable. In addition, being loaded at runtime means that individual code libraries can have their own initializers and clean up after their own tasks before being unloaded from memory
What's the meaning of dylib files?
I found that:
One Mach-O feature that hits many people by surprise is the strict
distinction between shared libraries and dynamically loadable modules.
On ELF systems both are the same; any piece of shared code can be used
as a library and for dynamic loading. Use otool -hv some_file to see
the filetype of some_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. However, they can not be
loaded as a module. (Side note: Shared libraries can be loaded
dynamically through an API. However, that API is different from the
API for bundles and the semantics make it useless for an dlopen()
emulation. Most notably, shared libraries can not be unloaded.) [This
is no longer true—you can use dlopen() with both dylibs and bundles.
However, dylibs still can't be unloaded.]Loadable modules are called "bundles" in Mach-O speak. They have the
file type MH_BUNDLE. Since no component involved cares about it, they
can carry any extension. The extension .bundle is recommended by
Apple, but most ported software uses .so for the sake of
compatibility. Bundles can be dynamically loaded and unloaded via dyld
APIs, and there is a wrapper that emulates dlopen() on top of that
API. [dlopen is now the preferred API.] 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.To compile a normal shared library on OS X, you should use -dynamiclib
and the extension .dylib. -fPIC is the default.
What are the g++ flags to build a true .so/MH_BUNDLE shared library on mac osx (not a dylib)?
If you want to build a bundle use -bundle
instead of -dynamiclib
when you're making the file.
The most obvious difference between bundles and dylibs is that you can link to a dylib at compile time.
e.g. g++ -o testfile testcode.c -lmylib
will link to libmylib.dylib
, while if you attempt to link a bundle you get:
ld: can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB) file 'test.bundle' for architecture x86_64
This is the biggest difference - you can't link a bundle dynamically, but instead have to dlopen
or use the Object File Image Functions. I'd steer away from the OS X only functions - they are deprecated, and you can get all the functionality you need from the dl*
functions instead.
As to building each, I'll give an example:
object file test.o
, making a dylib:
g++ -dynamiclib -o test.dylib test.o
making a bundle:
g++ -bundle -o test.bundle test.o
linking a bundle at run-time & getting a symbol:
void *v = dlopen("test.bundle", RTLD_LOCAL);
// declare func_ptr as a pointer to a fn taking void, returning an int
int (*func_ptr)(void);
func_ptr = (int (*)(void))dlsym(v, "symbol");
linking a bundle using old routines (seriously, don't do this):
#include <mach-o/dyld.h>
int rc;
NSObjectFileImage img;
NSModule handle;
NSSymbol sym;
rc = NSCreateObjectFileImageFromFile("test.bundle", &img);
if (rc != NSObjectFileImageSuccess) {
fprintf(stderr, "Could not load libanswer.bundle.\n");
exit(-1);
}
/* Get a handle for the bundle. */
handle = NSLinkModule(img, "test.bundle", FALSE);
/* Look up the get_answer function. */
sym = NSLookupSymbolInModule(handle, "_get_answer");
if (sym == NULL)
{
fprintf(stderr, "Could not find symbol: _get_answer.\n");
exit(-2);
}
int (*func_ptr)(void);
func_ptr = NSAddressOfSymbol(sym);
if you're compiling with clang, then you'll get a bunch of warnings like:
warning: 'NSCreateObjectFileImageFromFile' is deprecated: first deprecated in OS X 10.5
i.e. please don't use these functions.
Related Topics
Library Function For Permutation and Combination in C++
How to Link Opencv in Qtcreator and Use Qt Library
Removing Item from Vector, While in C++11 Range 'For' Loop
How to Increase the Re-Usability of This Key-Oriented Access-Protection Pattern
Lock-Free Progress Guarantees in a Circular Buffer Queue
Copying a Polymorphic Object in C++
Py_Initialize Fails - Unable to Load the File System Codec
Deprecated Header ≪Codecvt≫ Replacement
When Were the 'And' and 'Or' Alternative Tokens Introduced in C++
How to Open an Std::Fstream (Ofstream or Ifstream) With a Unicode Filename
Using Stdlib'S Rand() from Multiple Threads
Why Will Std::Sort Crash If the Comparison Function Is Not as Operator ≪
Atomic Double Floating Point or Sse/Avx Vector Load/Store on X86_64
Define Bitset Size At Initialization
On Which Platforms Does Integer Divide by Zero Trigger a Floating Point Exception
What Is Special About Numbers Starting With Zero
Opengl - Index Buffers Difficulties
C++ Performance Challenge: Integer to Std::String Conversion