build script: merging of installations with missing files and directories

This commit is contained in:
alexey.lysiuk 2020-12-28 10:58:50 +02:00
parent f0b23e87f2
commit 302a21f6b6

View file

@ -1745,6 +1745,9 @@ class Builder(object):
content = None content = None
for path in paths: for path in paths:
if not os.path.exists(path):
return False
with open(path, 'rb') as f: with open(path, 'rb') as f:
if content: if content:
if content != f.read(): if content != f.read():
@ -1755,48 +1758,74 @@ class Builder(object):
return True return True
@staticmethod @staticmethod
def _merge_install_paths(src_paths: typing.Sequence[str], dst_path: str): def _merge_file(src: os.DirEntry, src_sub_paths: typing.Sequence[str], dst_path: str):
with open(src.path, 'rb') as f:
header = f.read(8)
is_executable = header[:4] == b'\xcf\xfa\xed\xfe'
is_library = header == b'!<arch>\n'
if is_executable or is_library:
# Merge executable and library files
dst_file = dst_path + os.sep + src.name
args = ['lipo']
args += src_sub_paths
args += ['-create', '-output', dst_file]
subprocess.check_call(args)
# TODO: check if ad-hoc code signing is really needed
# See https://github.com/Homebrew/brew/commit/e945b1c42ab44feb1c6814f47cc833d76b1a921c
if is_executable:
args = ('codesign', '--sign', '-', dst_file)
subprocess.check_call(args)
else:
if not Builder._compare_files(src_sub_paths):
print(f'WARNING: Source files for {dst_path + os.sep + src.name} don\'t match')
shutil.copy(src_sub_paths[0], dst_path)
@staticmethod
def _merge_missing_files(src_paths: typing.Sequence[str], dst_path: str):
shifted_src_paths = [path for path in src_paths]
last_path_index = len(src_paths) - 1
for _ in range(last_path_index):
shifted_src_paths.append(shifted_src_paths[0])
del shifted_src_paths[0]
if not os.path.exists(shifted_src_paths[0]):
continue
Builder._merge_install_paths(shifted_src_paths, dst_path, missing_files_only=True)
@staticmethod
def _merge_install_paths(src_paths: typing.Sequence[str], dst_path: str, missing_files_only=False):
if len(src_paths) <= 1: if len(src_paths) <= 1:
return return
if os.path.exists(dst_path): if not missing_files_only:
shutil.rmtree(dst_path) if os.path.exists(dst_path):
shutil.rmtree(dst_path)
os.makedirs(dst_path) os.makedirs(dst_path, exist_ok=True)
for src in os.scandir(src_paths[0]): for src in os.scandir(src_paths[0]):
src_sub_path = [path + os.sep + src.name for path in src_paths] src_sub_paths = [path + os.sep + src.name for path in src_paths]
if src.is_dir(): if src.is_dir():
Builder._merge_install_paths(src_sub_path, dst_path + os.sep + src.name) Builder._merge_install_paths(src_sub_paths, dst_path + os.sep + src.name, missing_files_only)
elif src.name.endswith('.la'): elif src.name.endswith('.la'):
# Skip libtool files # Skip libtool files
continue continue
elif missing_files_only:
for src_sub_path in src_sub_paths[1:]:
if not os.path.exists(src_sub_path):
shutil.copy(src_sub_paths[0], dst_path)
else: else:
with open(src.path, 'rb') as f: Builder._merge_file(src, src_sub_paths, dst_path)
header = f.read(8)
is_executable = header[:4] == b'\xcf\xfa\xed\xfe' if not missing_files_only:
is_library = header == b'!<arch>\n' Builder._merge_missing_files(src_paths, dst_path)
if is_executable or is_library:
# Merge executable and library files
dst_file = dst_path + os.sep + src.name
args = ['lipo']
args += src_sub_path
args += ['-create', '-output', dst_file]
subprocess.check_call(args)
# TODO: check if ad-hoc code signing is really needed
# See https://github.com/Homebrew/brew/commit/e945b1c42ab44feb1c6814f47cc833d76b1a921c
if is_executable:
args = ('codesign', '--sign', '-', dst_file)
subprocess.check_call(args)
else:
if not Builder._compare_files(src_sub_path):
print(f'WARNING: Source files for {dst_path + os.sep + src.name} don\'t match')
shutil.copy(src_sub_path[0], dst_path)
def architecture(self) -> str: def architecture(self) -> str:
return self.platform.architecture if self.platform else '' return self.platform.architecture if self.platform else ''