taisei/scripts/macos-install-dylibs.py

85 lines
2.5 KiB
Python
Executable file

#!/usr/bin/env python3
#
# Install dylib dependencies, strip debugging symbols, and deal with the shitfucked digital abortion that is the macOS dynamic linker.
#
import re
import sys
import subprocess
import itertools
import shutil
from os import chmod, environ, pathsep
from pathlib import Path
build_root = Path(environ['MESON_BUILD_ROOT'])
source_root = Path(environ['MESON_SOURCE_ROOT'])
install_prefix = Path(environ['MESON_INSTALL_DESTDIR_PREFIX'])
args = sys.argv[1:]
macos_lib_paths = filter(None, (Path(x) for x in args.pop(0).split(pathsep)))
macos_tool_paths = filter(None, (Path(x) for x in args.pop(0).split(pathsep)))
macos_tool_prefix = args.pop(0)
if macos_tool_paths:
environ['PATH'] = pathsep.join(itertools.chain((str(p) for p in macos_tool_paths), [environ['PATH']]))
exe_path = install_prefix / 'Taisei.app' / 'Contents' / 'MacOS' / 'Taisei'
dylib_dir_path = exe_path.parent / 'dylibs'
dylib_dir_path.mkdir(mode=0o755, parents=True, exist_ok=True)
def tool(name):
def func(*args):
cmd = [macos_tool_prefix + name] + list(args)
print(' '.join(('{0!r}' if ' ' in str(s) else '{0}').format(str(s)) for s in cmd))
return subprocess.check_output(cmd, universal_newlines=True)
return func
otool = tool('otool')
install_name_tool = tool('install_name_tool')
strip = tool('strip')
def fix_libs(opath):
handled = set()
regex = re.compile(r'\s*(.*?\.dylib) \(')
def install(src, dst):
src = str(src)
dst = str(dst)
print('Installing {0} as {1}'.format(src, dst))
shutil.copy(str(src), str(dst))
chmod(str(dst), 0o755)
def fix(path):
for lib in regex.findall(otool('-L', path)):
if lib.startswith('/usr/lib') or lib.startswith('@'):
continue
src_lib_path = Path(lib)
dst_lib_path = dylib_dir_path / src_lib_path.name
install_name_tool(path, '-change', lib, '@executable_path/dylibs/{0}'.format(dst_lib_path.name))
if dst_lib_path in handled:
continue
install(src_lib_path, dst_lib_path)
handled.add(dst_lib_path)
fix(dst_lib_path)
install_name_tool(path, '-id', path.name)
strip('-S', path)
fix(opath)
return handled
new_files = fix_libs(exe_path)
if new_files:
with (build_root / 'meson-logs' / 'install-log.txt').open('a') as f:
f.write('# ...except when it does :^)\n')
for i in new_files:
f.write('{0}\n'.format(str(i)))