From 302a21f6b673e020b24e719c637539d6ad6701ff Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Mon, 28 Dec 2020 10:58:50 +0200 Subject: [PATCH] build script: merging of installations with missing files and directories --- build.py | 87 +++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 29 deletions(-) diff --git a/build.py b/build.py index 1db69575..01d78c70 100755 --- a/build.py +++ b/build.py @@ -1745,6 +1745,9 @@ class Builder(object): content = None for path in paths: + if not os.path.exists(path): + return False + with open(path, 'rb') as f: if content: if content != f.read(): @@ -1755,48 +1758,74 @@ class Builder(object): return True @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'!\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: return - if os.path.exists(dst_path): - shutil.rmtree(dst_path) + if not missing_files_only: + 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]): - 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(): - 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'): # Skip libtool files 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: - with open(src.path, 'rb') as f: - header = f.read(8) + Builder._merge_file(src, src_sub_paths, dst_path) - is_executable = header[:4] == b'\xcf\xfa\xed\xfe' - is_library = header == b'!\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_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) + if not missing_files_only: + Builder._merge_missing_files(src_paths, dst_path) def architecture(self) -> str: return self.platform.architecture if self.platform else ''