mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 16:58:40 -04:00
deploy-ng: rewrite relative dependencies in macOS dylibs
This commit is contained in:
parent
3a2a29a1aa
commit
b7e7986198
52
direct/src/dist/commands.py
vendored
52
direct/src/dist/commands.py
vendored
@ -624,7 +624,7 @@ class build_apps(setuptools.Command):
|
||||
search_path = [builddir]
|
||||
if use_wheels:
|
||||
search_path.append(os.path.join(p3dwhlfn, 'deploy_libs'))
|
||||
self.copy_dependencies(open(target_path, 'rb'), builddir, search_path, stub_name)
|
||||
self.copy_dependencies(target_path, builddir, search_path, stub_name)
|
||||
|
||||
freezer_extras.update(freezer.extras)
|
||||
freezer_modules.update(freezer.getAllModuleNames())
|
||||
@ -869,7 +869,7 @@ class build_apps(setuptools.Command):
|
||||
return
|
||||
|
||||
for dep in self.exclude_dependencies:
|
||||
if dep.matches_file(name):
|
||||
if dep.matches_file(name):
|
||||
return
|
||||
|
||||
for dir in search_path:
|
||||
@ -957,14 +957,15 @@ class build_apps(setuptools.Command):
|
||||
|
||||
self.copy(source_path, target_path)
|
||||
|
||||
fp = open(target_path, 'rb')
|
||||
source_dir = os.path.dirname(source_path)
|
||||
target_dir = os.path.dirname(target_path)
|
||||
base = os.path.basename(target_path)
|
||||
self.copy_dependencies(fp, target_dir, search_path + [source_dir], base)
|
||||
self.copy_dependencies(target_path, target_dir, search_path + [source_dir], base)
|
||||
|
||||
def copy_dependencies(self, fp, target_dir, search_path, referenced_by):
|
||||
""" Copies the dependencies of the given open file. """
|
||||
def copy_dependencies(self, target_path, target_dir, search_path, referenced_by):
|
||||
""" Copies the dependencies of target_path into target_dir. """
|
||||
|
||||
fp = open(target_path, 'rb+')
|
||||
|
||||
# What kind of magic does the file contain?
|
||||
deps = []
|
||||
@ -983,20 +984,21 @@ class build_apps(setuptools.Command):
|
||||
|
||||
elif magic in (b'\xCE\xFA\xED\xFE', b'\xCF\xFA\xED\xFE'):
|
||||
# A Mach-O file, as used on macOS.
|
||||
deps = self._read_dependencies_macho(fp, '<')
|
||||
deps = self._read_dependencies_macho(fp, '<', flatten=True)
|
||||
|
||||
elif magic in (b'\xFE\xED\xFA\xCE', b'\xFE\xED\xFA\xCF'):
|
||||
deps = self._read_dependencies_macho(fp, '>')
|
||||
rel_dir = os.path.relpath(target_dir, os.path.dirname(target_path))
|
||||
deps = self._read_dependencies_macho(fp, '>', flatten=True)
|
||||
|
||||
elif magic in (b'\xCA\xFE\xBA\xBE', b'\xBE\xBA\xFE\xCA'):
|
||||
# A fat file, containing multiple Mach-O binaries. In the future,
|
||||
# we may want to extract the one containing the architecture we
|
||||
# are building for.
|
||||
deps = self._read_dependencies_fat(fp, False)
|
||||
deps = self._read_dependencies_fat(fp, False, flatten=True)
|
||||
|
||||
elif magic in (b'\xCA\xFE\xBA\xBF', b'\xBF\xBA\xFE\xCA'):
|
||||
# A 64-bit fat file.
|
||||
deps = self._read_dependencies_fat(fp, True)
|
||||
deps = self._read_dependencies_fat(fp, True, flatten=True)
|
||||
|
||||
# If we discovered any dependencies, recursively add those.
|
||||
for dep in deps:
|
||||
@ -1065,9 +1067,14 @@ class build_apps(setuptools.Command):
|
||||
search_path += rpath
|
||||
return needed
|
||||
|
||||
def _read_dependencies_macho(self, fp, endian):
|
||||
def _read_dependencies_macho(self, fp, endian, flatten=False):
|
||||
""" Having read the first 4 bytes of the Mach-O file, fetches the
|
||||
dependent libraries and returns those as a list. """
|
||||
dependent libraries and returns those as a list.
|
||||
|
||||
If flatten is True, if the dependencies contain paths like
|
||||
@loader_path/../.dylibs/libsomething.dylib, it will rewrite them to
|
||||
instead contain @loader_path/libsomething.dylib if possible.
|
||||
This requires the file pointer to be opened in rb+ mode. """
|
||||
|
||||
cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags = \
|
||||
struct.unpack(endian + 'IIIIII', fp.read(24))
|
||||
@ -1086,17 +1093,30 @@ class build_apps(setuptools.Command):
|
||||
|
||||
if cmd == 0x0c: # LC_LOAD_DYLIB
|
||||
dylib = cmd_data[16:].decode('ascii').split('\x00', 1)[0]
|
||||
orig = dylib
|
||||
|
||||
if dylib.startswith('@loader_path/../Frameworks/'):
|
||||
dylib = dylib.replace('@loader_path/../Frameworks/', '')
|
||||
if dylib.startswith('@executable_path/../Frameworks/'):
|
||||
elif dylib.startswith('@executable_path/../Frameworks/'):
|
||||
dylib = dylib.replace('@executable_path/../Frameworks/', '')
|
||||
if dylib.startswith('@loader_path/'):
|
||||
elif dylib.startswith('@loader_path/'):
|
||||
dylib = dylib.replace('@loader_path/', '')
|
||||
|
||||
# Do we need to flatten the relative reference?
|
||||
if '/' in dylib and flatten:
|
||||
new_dylib = '@loader_path/' + os.path.basename(dylib)
|
||||
str_size = len(cmd_data) - 16
|
||||
if len(new_dylib) < str_size:
|
||||
fp.seek(-str_size, os.SEEK_CUR)
|
||||
fp.write(new_dylib.encode('ascii').ljust(str_size, b'\0'))
|
||||
else:
|
||||
self.warn('Unable to rewrite dependency {}'.format(orig))
|
||||
|
||||
load_dylibs.append(dylib)
|
||||
|
||||
return load_dylibs
|
||||
|
||||
def _read_dependencies_fat(self, fp, is_64bit):
|
||||
def _read_dependencies_fat(self, fp, is_64bit, flatten=False):
|
||||
num_fat, = struct.unpack('>I', fp.read(4))
|
||||
|
||||
# After the header we get a table of executables in this fat file,
|
||||
@ -1126,7 +1146,7 @@ class build_apps(setuptools.Command):
|
||||
# Not a Mach-O file we can read.
|
||||
continue
|
||||
|
||||
for dep in self._read_dependencies_macho(fp, endian):
|
||||
for dep in self._read_dependencies_macho(fp, endian, flatten=flatten):
|
||||
if dep not in deps:
|
||||
deps.append(dep)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user