If you haven’t already read Dynamic Library Identification, read that before reading this.
If you have questions or comments about this, start a new thread here on DevForums. Tag it with Linker so that I see it.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Dynamic Library Full Path Alternative
In most cases it’s better to use an rpath-relative install name for your dynamic library. See Dynamic Library Standard Setup for Apps for an explanation as to why. There is, however, one well-supported alternative: a full path.
IMPORTANT This technique is only viable on macOS. On iOS and its child platforms you must use an rpath-relative install name.
Back in the early days of macOS, using a full path as the install name was super common. A third-party developer might install a framework in /Library/Frameworks
with the express understanding that it would be used by other third-party apps.
In recent years this technique has waned in popularity because of the hardened runtime. The hardened runtime enables library validation, meaning that your process can only load code signed by Apple or signed by your own team. That makes it hard for multiple developers to shared code in this way. While it’s possible to disable library validation, that reduces the security of your product [1] and can cause Gatekeeper problems [2].
Using a full path as the install name is still useful for developers who ship multiple apps with a lot of common code. However, there are factors that work against that as well, notably user expecting to be able to install an app by dragging it the Applications folder and, more importantly, uninstall it by dragging it to the Trash.
[1] Starting with macOS 14 beta you can selective relax this restriction. See WWDC 2023 Session 10266 Protect your Mac app with environment constraints for the details.
[2] See Resolving Gatekeeper Problems Caused by Dangling Load Command Paths.
Adopting the Full Path Alternative
Adopting this technique is super simple:
-
Choose a full path for your dynamic library. Typically this will be within
/Library/Frameworks
but other directories, like a subdirectory within/Library/Application Support
, also work just fine. -
Set the install name of your dynamic library to that path.
-
When deploying, install your dynamic library at that path.
-
When building, either link your app to your dynamic library or to a stub library that references that path. For more information about stub libraries, see An Apple Library Primer.
This technique does have one notable drawback: It complicates your development process. It’s not very practical to install the library every time you rebuild it [1].
You can get around that using dynamic library environment variables, like DYLD_LIBRARY_PATH
and DYLD_FRAMEWORK_PATH
. For the details, see the dyld
man page. However, be aware that these are disabled by default by the hardened runtime.
[1] If you do go down that path, avoid the pitfall described in Updating Mac Software.