summaryrefslogtreecommitdiff
path: root/lib/spack/external/macholib/MachOStandalone.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/spack/external/macholib/MachOStandalone.py')
-rw-r--r--lib/spack/external/macholib/MachOStandalone.py173
1 files changed, 0 insertions, 173 deletions
diff --git a/lib/spack/external/macholib/MachOStandalone.py b/lib/spack/external/macholib/MachOStandalone.py
deleted file mode 100644
index 6ce154227c..0000000000
--- a/lib/spack/external/macholib/MachOStandalone.py
+++ /dev/null
@@ -1,173 +0,0 @@
-import os
-from collections import deque
-
-from macholib.dyld import framework_info
-from macholib.MachOGraph import MachOGraph, MissingMachO
-from macholib.util import (
- flipwritable,
- has_filename_filter,
- in_system_path,
- iter_platform_files,
- mergecopy,
- mergetree,
-)
-
-
-class ExcludedMachO(MissingMachO):
- pass
-
-
-class FilteredMachOGraph(MachOGraph):
- def __init__(self, delegate, *args, **kwargs):
- super(FilteredMachOGraph, self).__init__(*args, **kwargs)
- self.delegate = delegate
-
- def createNode(self, cls, name):
- cls = self.delegate.getClass(name, cls)
- res = super(FilteredMachOGraph, self).createNode(cls, name)
- return self.delegate.update_node(res)
-
- def locate(self, filename, loader=None):
- newname = super(FilteredMachOGraph, self).locate(filename, loader)
- if newname is None:
- return None
- return self.delegate.locate(newname, loader=loader)
-
-
-class MachOStandalone(object):
- def __init__(self, base, dest=None, graph=None, env=None, executable_path=None):
- self.base = os.path.join(os.path.abspath(base), "")
- if dest is None:
- dest = os.path.join(self.base, "Contents", "Frameworks")
- self.dest = dest
- self.mm = FilteredMachOGraph(
- self, graph=graph, env=env, executable_path=executable_path
- )
- self.changemap = {}
- self.excludes = []
- self.pending = deque()
-
- def update_node(self, m):
- return m
-
- def getClass(self, name, cls):
- if in_system_path(name):
- return ExcludedMachO
- for base in self.excludes:
- if name.startswith(base):
- return ExcludedMachO
- return cls
-
- def locate(self, filename, loader=None):
- if in_system_path(filename):
- return filename
- if filename.startswith(self.base):
- return filename
- for base in self.excludes:
- if filename.startswith(base):
- return filename
- if filename in self.changemap:
- return self.changemap[filename]
- info = framework_info(filename)
- if info is None:
- res = self.copy_dylib(filename)
- self.changemap[filename] = res
- return res
- else:
- res = self.copy_framework(info)
- self.changemap[filename] = res
- return res
-
- def copy_dylib(self, filename):
- # When the filename is a symlink use the basename of the target of
- # the link as the name in standalone bundle. This avoids problems
- # when two libraries link to the same dylib but using different
- # symlinks.
- if os.path.islink(filename):
- dest = os.path.join(self.dest, os.path.basename(os.path.realpath(filename)))
- else:
- dest = os.path.join(self.dest, os.path.basename(filename))
-
- if not os.path.exists(dest):
- self.mergecopy(filename, dest)
- return dest
-
- def mergecopy(self, src, dest):
- return mergecopy(src, dest)
-
- def mergetree(self, src, dest):
- return mergetree(src, dest)
-
- def copy_framework(self, info):
- dest = os.path.join(self.dest, info["shortname"] + ".framework")
- destfn = os.path.join(self.dest, info["name"])
- src = os.path.join(info["location"], info["shortname"] + ".framework")
- if not os.path.exists(dest):
- self.mergetree(src, dest)
- self.pending.append((destfn, iter_platform_files(dest)))
- return destfn
-
- def run(self, platfiles=None, contents=None):
- mm = self.mm
- if contents is None:
- contents = "@executable_path/.."
- if platfiles is None:
- platfiles = iter_platform_files(self.base)
-
- for fn in platfiles:
- mm.run_file(fn)
-
- while self.pending:
- fmwk, files = self.pending.popleft()
- ref = mm.findNode(fmwk)
- for fn in files:
- mm.run_file(fn, caller=ref)
-
- changemap = {}
- skipcontents = os.path.join(os.path.dirname(self.dest), "")
- machfiles = []
-
- for node in mm.flatten(has_filename_filter):
- machfiles.append(node)
- dest = os.path.join(
- contents,
- os.path.normpath(node.filename[len(skipcontents) :]), # noqa: E203
- )
- changemap[node.filename] = dest
-
- def changefunc(path):
- if path.startswith("@loader_path/"):
- # This is a quick hack for py2app: In that
- # usecase paths like this are found in the load
- # commands of relocatable wheels. Those don't
- # need rewriting.
- return path
-
- res = mm.locate(path)
- rv = changemap.get(res)
- if rv is None and path.startswith("@loader_path/"):
- rv = changemap.get(mm.locate(mm.trans_table.get((node.filename, path))))
- return rv
-
- for node in machfiles:
- fn = mm.locate(node.filename)
- if fn is None:
- continue
- rewroteAny = False
- for _header in node.headers:
- if node.rewriteLoadCommands(changefunc):
- rewroteAny = True
- if rewroteAny:
- old_mode = flipwritable(fn)
- try:
- with open(fn, "rb+") as f:
- for _header in node.headers:
- f.seek(0)
- node.write(f)
- f.seek(0, 2)
- f.flush()
- finally:
- flipwritable(fn, old_mode)
-
- allfiles = [mm.locate(node.filename) for node in machfiles]
- return set(filter(None, allfiles))