summaryrefslogtreecommitdiff
path: root/lib/spack/external/_vendoring/macholib/dyld.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/spack/external/_vendoring/macholib/dyld.py')
-rw-r--r--lib/spack/external/_vendoring/macholib/dyld.py228
1 files changed, 228 insertions, 0 deletions
diff --git a/lib/spack/external/_vendoring/macholib/dyld.py b/lib/spack/external/_vendoring/macholib/dyld.py
new file mode 100644
index 0000000000..fcb23198cb
--- /dev/null
+++ b/lib/spack/external/_vendoring/macholib/dyld.py
@@ -0,0 +1,228 @@
+"""
+dyld emulation
+"""
+
+import ctypes
+import os
+import platform
+import sys
+from itertools import chain
+
+from macholib.dylib import dylib_info
+from macholib.framework import framework_info
+
+__all__ = ["dyld_find", "framework_find", "framework_info", "dylib_info"]
+
+if sys.platform == "darwin" and [
+ int(x) for x in platform.mac_ver()[0].split(".")[:2]
+] >= [10, 16]:
+ try:
+ libc = ctypes.CDLL("libSystem.dylib")
+
+ except OSError:
+ _dyld_shared_cache_contains_path = None
+
+ else:
+ try:
+ _dyld_shared_cache_contains_path = libc._dyld_shared_cache_contains_path
+ except AttributeError:
+ _dyld_shared_cache_contains_path = None
+
+ else:
+ _dyld_shared_cache_contains_path.restype = ctypes.c_bool
+ _dyld_shared_cache_contains_path.argtypes = [ctypes.c_char_p]
+
+ if sys.version_info[0] != 2:
+ __dyld_shared_cache_contains_path = _dyld_shared_cache_contains_path
+
+ def _dyld_shared_cache_contains_path(path):
+ return __dyld_shared_cache_contains_path(path.encode())
+
+else:
+ _dyld_shared_cache_contains_path = None
+
+# These are the defaults as per man dyld(1)
+#
+_DEFAULT_FRAMEWORK_FALLBACK = [
+ os.path.expanduser("~/Library/Frameworks"),
+ "/Library/Frameworks",
+ "/Network/Library/Frameworks",
+ "/System/Library/Frameworks",
+]
+
+_DEFAULT_LIBRARY_FALLBACK = [
+ os.path.expanduser("~/lib"),
+ "/usr/local/lib",
+ "/lib",
+ "/usr/lib",
+]
+
+if sys.version_info[0] == 2:
+
+ def _ensure_utf8(s):
+ if isinstance(s, unicode): # noqa: F821
+ return s.encode("utf8")
+ return s
+
+else:
+
+ def _ensure_utf8(s):
+ if s is not None and not isinstance(s, str):
+ raise ValueError(s)
+ return s
+
+
+def _dyld_env(env, var):
+ if env is None:
+ env = os.environ
+ rval = env.get(var)
+ if rval is None or rval == "":
+ return []
+ return rval.split(":")
+
+
+def dyld_image_suffix(env=None):
+ if env is None:
+ env = os.environ
+ return env.get("DYLD_IMAGE_SUFFIX")
+
+
+def dyld_framework_path(env=None):
+ return _dyld_env(env, "DYLD_FRAMEWORK_PATH")
+
+
+def dyld_library_path(env=None):
+ return _dyld_env(env, "DYLD_LIBRARY_PATH")
+
+
+def dyld_fallback_framework_path(env=None):
+ return _dyld_env(env, "DYLD_FALLBACK_FRAMEWORK_PATH")
+
+
+def dyld_fallback_library_path(env=None):
+ return _dyld_env(env, "DYLD_FALLBACK_LIBRARY_PATH")
+
+
+def dyld_image_suffix_search(iterator, env=None):
+ """For a potential path iterator, add DYLD_IMAGE_SUFFIX semantics"""
+ suffix = dyld_image_suffix(env)
+ if suffix is None:
+ return iterator
+
+ def _inject(iterator=iterator, suffix=suffix):
+ for path in iterator:
+ if path.endswith(".dylib"):
+ yield path[: -len(".dylib")] + suffix + ".dylib"
+ else:
+ yield path + suffix
+ yield path
+
+ return _inject()
+
+
+def dyld_override_search(name, env=None):
+ # If DYLD_FRAMEWORK_PATH is set and this dylib_name is a
+ # framework name, use the first file that exists in the framework
+ # path if any. If there is none go on to search the DYLD_LIBRARY_PATH
+ # if any.
+
+ framework = framework_info(name)
+
+ if framework is not None:
+ for path in dyld_framework_path(env):
+ yield os.path.join(path, framework["name"])
+
+ # If DYLD_LIBRARY_PATH is set then use the first file that exists
+ # in the path. If none use the original name.
+ for path in dyld_library_path(env):
+ yield os.path.join(path, os.path.basename(name))
+
+
+def dyld_executable_path_search(name, executable_path=None):
+ # If we haven't done any searching and found a library and the
+ # dylib_name starts with "@executable_path/" then construct the
+ # library name.
+ if name.startswith("@executable_path/") and executable_path is not None:
+ yield os.path.join(
+ executable_path, name[len("@executable_path/") :] # noqa: E203
+ )
+
+
+def dyld_loader_search(name, loader_path=None):
+ # If we haven't done any searching and found a library and the
+ # dylib_name starts with "@loader_path/" then construct the
+ # library name.
+ if name.startswith("@loader_path/") and loader_path is not None:
+ yield os.path.join(loader_path, name[len("@loader_path/") :]) # noqa: E203
+
+
+def dyld_default_search(name, env=None):
+ yield name
+
+ framework = framework_info(name)
+
+ if framework is not None:
+ fallback_framework_path = dyld_fallback_framework_path(env)
+
+ if fallback_framework_path:
+ for path in fallback_framework_path:
+ yield os.path.join(path, framework["name"])
+
+ else:
+ for path in _DEFAULT_FRAMEWORK_FALLBACK:
+ yield os.path.join(path, framework["name"])
+
+ fallback_library_path = dyld_fallback_library_path(env)
+ if fallback_library_path:
+ for path in fallback_library_path:
+ yield os.path.join(path, os.path.basename(name))
+
+ else:
+ for path in _DEFAULT_LIBRARY_FALLBACK:
+ yield os.path.join(path, os.path.basename(name))
+
+
+def dyld_find(name, executable_path=None, env=None, loader_path=None):
+ """
+ Find a library or framework using dyld semantics
+ """
+ name = _ensure_utf8(name)
+ executable_path = _ensure_utf8(executable_path)
+ for path in dyld_image_suffix_search(
+ chain(
+ dyld_override_search(name, env),
+ dyld_executable_path_search(name, executable_path),
+ dyld_loader_search(name, loader_path),
+ dyld_default_search(name, env),
+ ),
+ env,
+ ):
+ if (
+ _dyld_shared_cache_contains_path is not None
+ and _dyld_shared_cache_contains_path(path)
+ ):
+ return path
+ if os.path.isfile(path):
+ return path
+ raise ValueError("dylib %s could not be found" % (name,))
+
+
+def framework_find(fn, executable_path=None, env=None):
+ """
+ Find a framework using dyld semantics in a very loose manner.
+
+ Will take input such as:
+ Python
+ Python.framework
+ Python.framework/Versions/Current
+ """
+ try:
+ return dyld_find(fn, executable_path=executable_path, env=env)
+ except ValueError:
+ pass
+ fmwk_index = fn.rfind(".framework")
+ if fmwk_index == -1:
+ fmwk_index = len(fn)
+ fn += ".framework"
+ fn = os.path.join(fn, os.path.basename(fn[:fmwk_index]))
+ return dyld_find(fn, executable_path=executable_path, env=env)