.dylib is the dynamic library extension on OSX, 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)
解决方案
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).