dyld - the dynamic linker
DYLD_FRAMEWORK_PATH
DYLD_FALLBACK_FRAMEWORK_PATH
DYLD_VERSIONED_FRAMEWORK_PATH
DYLD_LIBRARY_PATH
DYLD_FALLBACK_LIBRARY_PATH
DYLD_VERSIONED_LIBRARY_PATH
DYLD_IMAGE_SUFFIX
DYLD_INSERT_LIBRARIES
DYLD_PRINT_TO_FILE
DYLD_PRINT_LIBRARIES
DYLD_PRINT_LOADERS
DYLD_PRINT_SEARCHING
DYLD_PRINT_APIS
DYLD_PRINT_BINDINGS
DYLD_PRINT_INITIALIZERS
DYLD_PRINT_SEGMENTS
DYLD_PRINT_ENV
DYLD_PRINT_LINKS_WITH
DYLD_SHARED_REGION
DYLD_SHARED_CACHE_DIR
The dynamic linker (dyld) checks the following environment
variables during the launch of each process.
Note: If System Integrity Protection is enabled, these environment variables
are ignored when executing binaries protected by System Integrity
Protection.
- DYLD_FRAMEWORK_PATH
- This is a colon separated list of directories that contain frameworks. The
dynamic linker searches these directories before it searches for the
framework by its install name. It allows you to test new versions of
existing frameworks. (A framework is a library install name that ends in
the form XXX.framework/Versions/A/XXX or XXX.framework/XXX, where XXX and
A are any name.)
- For each framework that a program uses, the dynamic linker looks for the
framework in each directory in DYLD_FRAMEWORK_PATH in turn.
If it looks in all those directories and can't find the framework, it uses
whatever it would have loaded if DYLD_FRAMEWORK_PATH had not been
set.
- Use the -L option to otool(1) to discover the frameworks and
shared libraries that the executable is linked against.
- DYLD_FALLBACK_FRAMEWORK_PATH
- This is a colon separated list of directories that contain frameworks. If
a framework is not found at its install path, dyld uses this as a list of
directories to search for the framework.
For new binaries (Fall 2023 or later) there is no default
fallback. For older binaries, there is a default fallback search path
of: /Library/Frameworks:/System/Library/Frameworks
- DYLD_VERSIONED_FRAMEWORK_PATH
- This is a colon separated list of directories that contain potential
override frameworks. The dynamic linker searches these directories for
frameworks. For each framework found dyld looks at its LC_ID_DYLIB and
gets the current_version and install name. Dyld then looks for the
framework at the install name path. Whichever has the larger
current_version value will be used in the process whenever a framework
with that install name is required. This is similar to DYLD_FRAMEWORK_PATH
except instead of always overriding, it only overrides if the supplied
framework is newer. Note: dyld does not check the framework's Info.plist
to find its version. Dyld only checks the -current_version number supplied
when the framework was created.
- DYLD_LIBRARY_PATH
- This is a colon separated list of directories that contain libraries. The
dynamic linker searches these directories before it searches the default
locations for libraries. It allows you to test new versions of existing
libraries.
- For each dylib that a program uses, the dynamic linker looks for its leaf
name in each directory in DYLD_LIBRARY_PATH.
- Use the -L option to otool(1) to discover the frameworks and
shared libraries that the executable is linked against.
- DYLD_FALLBACK_LIBRARY_PATH
- This is a colon separated list of directories that contain libraries. If a
dylib is not found at its install path, dyld uses this as a list of
directories to search for the dylib.
For new binaries (Fall 2023 or later) there is no default. For
older binaries, there is a default fallback search path of:
/usr/local/lib:/usr/lib.
- DYLD_VERSIONED_LIBRARY_PATH
- This is a colon separated list of directories that contain potential
override libraries. The dynamic linker searches these directories for
dynamic libraries. For each library found dyld looks at its LC_ID_DYLIB
and gets the current_version and install name. Dyld then looks for the
library at the install name path. Whichever has the larger current_version
value will be used in the process whenever a dylib with that install name
is required. This is similar to DYLD_LIBRARY_PATH except instead of always
overriding, it only overrides is the supplied library is newer.
- DYLD_IMAGE_SUFFIX
- This is set to a string of a suffix to try to be used for all shared
libraries used by the program. For libraries ending in ".dylib"
the suffix is applied just before the ".dylib". For all other
libraries the suffix is appended to the library name. This is useful for
using conventional "_profile" and "_debug" libraries
and frameworks.
- DYLD_INSERT_LIBRARIES
- This is a colon separated list of additional dynamic libraries to load
before the ones specified in the program. If instead, your goal is to
substitute a library that would normally be loaded, use
DYLD_LIBRARY_PATH or DYLD_FRAMEWORK_PATH
instead.
- DYLD_PRINT_TO_FILE
- This is a path to a (writable) file. Normally, the dynamic linker writes
all logging output (triggered by DYLD_PRINT_* settings) to file descriptor
2 (which is usually stderr). But this setting causes the dynamic linker to
write logging output to the specified file.
- DYLD_PRINT_ENV
- If set, causes dyld to print a line of key=value for each environment
variable in the process.
- DYLD_PRINT_LIBRARIES
- If set, causes dyld to print a line for each mach-o image loaded into a
process. This is useful to make sure that the use of
DYLD_LIBRARY_PATH is getting what you want.
- DYLD_PRINT_LOADERS
- If set, causes dyld to print a line whether each image is tracked by a
JustInTimeLoader or a PrebuiltLoader. Additionally, it prints if a
PrebuiltLoaderSet was used to launch the process or if a PrebuiltLoader
was written to make the next launch faster.
- DYLD_PRINT_SEARCHING
- If set, causes dyld to print a line about each file system path checked
when searching for an image to load.
- DYLD_PRINT_INITIALIZERS
- If set, causes dyld to print out a line when running each initializer in
every image. Initializers run by dyld include constructors for C++
statically allocated objects, functions marked with
__attribute__((constructor)), and -init functions.
- DYLD_PRINT_APIS
- If set, causes dyld to print a line whenever a dyld API is called (e.g.
dlopen()).
- DYLD_PRINT_SEGMENTS
- If set, causes dyld to print out a line containing the name and address
range of each mach-o segment that dyld maps. In addition it prints
information about if the image was from the dyld shared cache.
- DYLD_PRINT_BINDINGS
- If set, causes dyld to print a line each time a symbolic name is
bound.
- DYLD_PRINT_LINKS_WITH
- If set to the leaf name of a mach-o image, dyld prints why that image was
loaded, including the chain of links from the main executable or
dlopen()ed image to the request image name. The leaf name needs to be the
actual leaf file/install name (e.g. "libz.1.dylib" and not one
of the aliases such as "libz.dylib"). When reporting the chain
of links the --> may contain a letter (-w-> is a weak link, -r->
is a re-export, -u-> is an upward link, -d-> is a delay-init
link).
- DYLD_SHARED_REGION
- This can be "use" (the default) or "private". Setting
it to "private" tells dyld to remove the shared region from the
process address space and mmap() back in a private copy of the dyld shared
cache in the shared region address range. This is only useful if the
shared cache on disk has been updated and is different than the shared
cache in use.
- DYLD_SHARED_CACHE_DIR
- This is a directory containing dyld shared cache files. This variable can
be used in conjunction with DYLD_SHARED_REGION=private to run a process
with an alternate shared cache.
Unlike many other operating systems, Darwin does not locate
dependent dynamic libraries via their leaf file name. Instead the full path
to each dylib is used (e.g. /usr/lib/libSystem.B.dylib). But there are times
when a full path is not appropriate; for instance, may want your binaries to
be installable in anywhere on the disk. To support that, there are three
@xxx/ variables that can be used as a path prefix. At runtime dyld
substitutes a dynamically generated path for the @xxx/ prefix.
- @executable_path/
- This variable is replaced with the path to the directory containing the
main executable for the process. This is useful for loading
dylibs/frameworks embedded in a .app directory. If the main executable
file is at /some/path/My.app/Contents/MacOS/My and a framework dylib file
is at /some/path/My.app/Contents/Frameworks/Foo.framework/Versions/A/Foo,
then the framework load path could be encoded as
@executable_path/../Frameworks/Foo.framework/Versions/A/Foo and the .app
directory could be moved around in the file system and dyld will still be
able to load the embedded framework.
- @loader_path/
- This variable is replaced with the path to the directory containing the
mach-o binary which contains the load command using @loader_path. Thus, in
every binary, @loader_path resolves to a different path, whereas
@executable_path always resolves to the same path. @loader_path is useful
as the load path for a framework/dylib embedded in a plug-in, if the final
file system location of the plugin-in unknown (so absolute paths cannot be
used) or if the plug-in is used by multiple applications (so
@executable_path cannot be used). If the plug-in mach-o file is at
/some/path/Myfilter.plugin/Contents/MacOS/Myfilter and a framework dylib
file is at
/some/path/Myfilter.plugin/Contents/Frameworks/Foo.framework/Versions/A/Foo,
then the framework load path could be encoded as
@loader_path/../Frameworks/Foo.framework/Versions/A/Foo and the
Myfilter.plugin directory could be moved around in the file system and
dyld will still be able to load the embedded framework.
- @rpath/
- Dyld maintains a current stack of paths called the run path list. When
@rpath is encountered it is substituted with each path in the run path
list until a loadable dylib if found. The run path stack is built from the
LC_RPATH load commands in the depencency chain that lead to the current
dylib load. You can add an LC_RPATH load command to an image with the
-rpath option to ld(1). You can even add a LC_RPATH load command path that
starts with @loader_path/, and it will push a path on the run path stack
that relative to the image containing the LC_RPATH. The use of @rpath is
most useful when you have a complex directory structure of programs and
dylibs which can be installed anywhere, but keep their relative positions.
This scenario could be implemented using @loader_path, but every client of
a dylib could need a different load path because its relative position in
the file system is different. The use of @rpath introduces a level of
indirection that simplifies things. You pick a location in your directory
structure as an anchor point. Each dylib then gets an install path that
starts with @rpath and is the path to the dylib relative to the anchor
point. Each main executable is linked with -rpath @loader_path/zzz, where
zzz is the path from the executable to the anchor point. At runtime dyld
sets it run path to be the anchor point, then each dylib is found relative
to the anchor point.
dyld_info(1), ld(1), otool(1)