From 5cdbe669655348f6ab53ae72502a42d05565b3c0 Mon Sep 17 00:00:00 2001 From: Isuru Fernando Date: Thu, 21 Mar 2024 12:47:49 -0500 Subject: [PATCH] ptimize calls to install_name_tool --- delocate/tools.py | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/delocate/tools.py b/delocate/tools.py index 6137d3ca..70e10de5 100644 --- a/delocate/tools.py +++ b/delocate/tools.py @@ -9,7 +9,9 @@ import time import warnings import zipfile +from collections import Counter from datetime import datetime +from itertools import chain from os import PathLike from os.path import exists, isdir from os.path import join as pjoin @@ -750,6 +752,8 @@ def get_rpaths(filename: str) -> Tuple[str, ...]: """Return a tuple of rpaths from the library `filename`. If `filename` is not a library then the returned tuple will be empty. + Duplicate rpaths will be returned if there are duplicate rpaths in the + Mach-O binary. Parameters ---------- @@ -819,8 +823,8 @@ def add_rpath(filename: str, newpath: str, ad_hoc_sign: bool = True) -> None: @ensure_writable -def delete_rpath( - filename: str, existing_path: str, ad_hoc_sign: bool = True +def _delete_rpaths( + filename: str, rpaths: List[str], ad_hoc_sign: bool = True ) -> None: """Remove rpath `newpath` from library `filename`. @@ -828,15 +832,23 @@ def delete_rpath( ---------- filename : str filename of library - existing_path : str - rpath to delete + rpaths : List[str] + rpaths to delete ad_hoc_sign : {True, False}, optional If True, sign file with ad-hoc signature """ - _run( - ["install_name_tool", "-delete_rpath", existing_path, filename], - check=True, - ) + rpaths = Counter(rpaths) + n = max(rpaths.values()) + for i in range(n): + args = [ + ("-delete_rpath", rpath) + for (rpath, count) in rpaths.items() + if i < count + ] + _run( + ["install_name_tool", *chain(*args), filename], + check=True, + ) if ad_hoc_sign: replace_signature(filename, "-") @@ -881,13 +893,15 @@ def _remove_absolute_rpaths(filename: str, ad_hoc_sign: bool = True) -> None: ad_hoc_sign : {True, False}, optional If True, sign file with ad-hoc signature """ - for rpath in get_rpaths(filename): - if not _is_rpath_sanitary(rpath): - logger.info("Sanitize: Deleting rpath %r from %r", rpath, filename) - # We can run these as one command to install_name_tool if there are - # no duplicates. When there are duplicates, we need to delete them - # separately. - delete_rpath(filename, rpath, ad_hoc_sign) + rpaths_to_delete = [ + rpath for rpath in get_rpaths(filename) if not _is_rpath_sanitary(rpath) + ] + logger.info( + "Sanitize: Deleting rpaths %r from %r", + ", ".join(rpaths_to_delete), + filename, + ) + _delete_rpaths(filename, rpaths_to_delete, ad_hoc_sign) def zip2dir(