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]
|
search_path = [builddir]
|
||||||
if use_wheels:
|
if use_wheels:
|
||||||
search_path.append(os.path.join(p3dwhlfn, 'deploy_libs'))
|
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_extras.update(freezer.extras)
|
||||||
freezer_modules.update(freezer.getAllModuleNames())
|
freezer_modules.update(freezer.getAllModuleNames())
|
||||||
@ -869,7 +869,7 @@ class build_apps(setuptools.Command):
|
|||||||
return
|
return
|
||||||
|
|
||||||
for dep in self.exclude_dependencies:
|
for dep in self.exclude_dependencies:
|
||||||
if dep.matches_file(name):
|
if dep.matches_file(name):
|
||||||
return
|
return
|
||||||
|
|
||||||
for dir in search_path:
|
for dir in search_path:
|
||||||
@ -957,14 +957,15 @@ class build_apps(setuptools.Command):
|
|||||||
|
|
||||||
self.copy(source_path, target_path)
|
self.copy(source_path, target_path)
|
||||||
|
|
||||||
fp = open(target_path, 'rb')
|
|
||||||
source_dir = os.path.dirname(source_path)
|
source_dir = os.path.dirname(source_path)
|
||||||
target_dir = os.path.dirname(target_path)
|
target_dir = os.path.dirname(target_path)
|
||||||
base = os.path.basename(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):
|
def copy_dependencies(self, target_path, target_dir, search_path, referenced_by):
|
||||||
""" Copies the dependencies of the given open file. """
|
""" Copies the dependencies of target_path into target_dir. """
|
||||||
|
|
||||||
|
fp = open(target_path, 'rb+')
|
||||||
|
|
||||||
# What kind of magic does the file contain?
|
# What kind of magic does the file contain?
|
||||||
deps = []
|
deps = []
|
||||||
@ -983,20 +984,21 @@ class build_apps(setuptools.Command):
|
|||||||
|
|
||||||
elif magic in (b'\xCE\xFA\xED\xFE', b'\xCF\xFA\xED\xFE'):
|
elif magic in (b'\xCE\xFA\xED\xFE', b'\xCF\xFA\xED\xFE'):
|
||||||
# A Mach-O file, as used on macOS.
|
# 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'):
|
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'):
|
elif magic in (b'\xCA\xFE\xBA\xBE', b'\xBE\xBA\xFE\xCA'):
|
||||||
# A fat file, containing multiple Mach-O binaries. In the future,
|
# A fat file, containing multiple Mach-O binaries. In the future,
|
||||||
# we may want to extract the one containing the architecture we
|
# we may want to extract the one containing the architecture we
|
||||||
# are building for.
|
# 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'):
|
elif magic in (b'\xCA\xFE\xBA\xBF', b'\xBF\xBA\xFE\xCA'):
|
||||||
# A 64-bit fat file.
|
# 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.
|
# If we discovered any dependencies, recursively add those.
|
||||||
for dep in deps:
|
for dep in deps:
|
||||||
@ -1065,9 +1067,14 @@ class build_apps(setuptools.Command):
|
|||||||
search_path += rpath
|
search_path += rpath
|
||||||
return needed
|
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
|
""" 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 = \
|
cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags = \
|
||||||
struct.unpack(endian + 'IIIIII', fp.read(24))
|
struct.unpack(endian + 'IIIIII', fp.read(24))
|
||||||
@ -1086,17 +1093,30 @@ class build_apps(setuptools.Command):
|
|||||||
|
|
||||||
if cmd == 0x0c: # LC_LOAD_DYLIB
|
if cmd == 0x0c: # LC_LOAD_DYLIB
|
||||||
dylib = cmd_data[16:].decode('ascii').split('\x00', 1)[0]
|
dylib = cmd_data[16:].decode('ascii').split('\x00', 1)[0]
|
||||||
|
orig = dylib
|
||||||
|
|
||||||
if dylib.startswith('@loader_path/../Frameworks/'):
|
if dylib.startswith('@loader_path/../Frameworks/'):
|
||||||
dylib = dylib.replace('@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/', '')
|
dylib = dylib.replace('@executable_path/../Frameworks/', '')
|
||||||
if dylib.startswith('@loader_path/'):
|
elif dylib.startswith('@loader_path/'):
|
||||||
dylib = dylib.replace('@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)
|
load_dylibs.append(dylib)
|
||||||
|
|
||||||
return load_dylibs
|
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))
|
num_fat, = struct.unpack('>I', fp.read(4))
|
||||||
|
|
||||||
# After the header we get a table of executables in this fat file,
|
# 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.
|
# Not a Mach-O file we can read.
|
||||||
continue
|
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:
|
if dep not in deps:
|
||||||
deps.append(dep)
|
deps.append(dep)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user