99import sys
1010import typing
1111
12+ from itertools import chain
13+
1214
1315if typing .TYPE_CHECKING :
14- from typing import List
16+ from typing import List , Optional , TypeVar
1517
1618 from mesonpy ._compat import Iterable , Path
1719
20+ T = TypeVar ('T' )
21+
22+
23+ def unique (values : List [T ]) -> List [T ]:
24+ r = []
25+ for value in values :
26+ if value not in r :
27+ r .append (value )
28+ return r
29+
1830
1931if sys .platform == 'win32' or sys .platform == 'cygwin' :
2032
21- def fix_rpath (filepath : Path , libs_relative_path : str ) -> None :
33+ def fix_rpath (filepath : Path , install_rpath : Optional [ str ], libs_rpath : Optional [ str ] ) -> None :
2234 pass
2335
2436elif sys .platform == 'darwin' :
@@ -35,13 +47,33 @@ def _get_rpath(filepath: Path) -> List[str]:
3547 rpath_tag = False
3648 return rpath
3749
38- def _replace_rpath (filepath : Path , old : str , new : str ) -> None :
39- subprocess .run (['install_name_tool' , '-rpath' , old , new , os .fspath (filepath )], check = True )
50+ def _delete_rpath (filepath : Path , rpath : Iterable [str ]) -> None :
51+ args = list (chain (* (('-delete_rpath' , path ) for path in rpath )))
52+ if not args :
53+ return
54+ subprocess .run (['install_name_tool' , * args , os .fspath (filepath )], check = True )
4055
41- def fix_rpath (filepath : Path , libs_relative_path : str ) -> None :
42- for path in _get_rpath (filepath ):
43- if path .startswith ('@loader_path/' ):
44- _replace_rpath (filepath , path , '@loader_path/' + libs_relative_path )
56+ def _add_rpath (filepath : Path , rpath : Iterable [str ]) -> None :
57+ args = list (chain (* (('-add_rpath' , path ) for path in rpath )))
58+ if not args :
59+ return
60+ subprocess .run (['install_name_tool' , * args , os .fspath (filepath )], check = True )
61+
62+ def fix_rpath (filepath : Path , install_rpath : Optional [str ], libs_rpath : Optional [str ]) -> None :
63+ old_rpath = _get_rpath (filepath )
64+ new_rpath = []
65+ if libs_rpath is not None :
66+ if libs_rpath == '.' :
67+ libs_rpath = ''
68+ for path in old_rpath :
69+ if path .startswith ('@loader_path/' ):
70+ new_rpath .append ('@loader_path/' + libs_rpath )
71+ if install_rpath :
72+ new_rpath .append (install_rpath )
73+ new_rpath = unique (new_rpath )
74+ if new_rpath != old_rpath :
75+ _delete_rpath (filepath , old_rpath )
76+ _add_rpath (filepath , new_rpath )
4577
4678elif sys .platform == 'sunos5' :
4779
@@ -59,13 +91,18 @@ def _get_rpath(filepath: Path) -> List[str]:
5991 def _set_rpath (filepath : Path , rpath : Iterable [str ]) -> None :
6092 subprocess .run (['/usr/bin/elfedit' , '-e' , 'dyn:rpath ' + ':' .join (rpath ), os .fspath (filepath )], check = True )
6193
62- def fix_rpath (filepath : Path , libs_relative_path : str ) -> None :
94+ def fix_rpath (filepath : Path , install_rpath : Optional [ str ], libs_rpath : Optional [ str ] ) -> None :
6395 old_rpath = _get_rpath (filepath )
6496 new_rpath = []
65- for path in old_rpath :
66- if path .startswith ('$ORIGIN/' ):
67- path = '$ORIGIN/' + libs_relative_path
68- new_rpath .append (path )
97+ if libs_rpath is not None :
98+ if libs_rpath == '.' :
99+ libs_rpath = ''
100+ for path in old_rpath :
101+ if path .startswith ('$ORIGIN/' ):
102+ new_rpath .append ('$ORIGIN/' + libs_rpath )
103+ if install_rpath :
104+ new_rpath .append (install_rpath )
105+ new_rpath = unique (new_rpath )
69106 if new_rpath != old_rpath :
70107 _set_rpath (filepath , new_rpath )
71108
@@ -79,12 +116,17 @@ def _get_rpath(filepath: Path) -> List[str]:
79116 def _set_rpath (filepath : Path , rpath : Iterable [str ]) -> None :
80117 subprocess .run (['patchelf' ,'--set-rpath' , ':' .join (rpath ), os .fspath (filepath )], check = True )
81118
82- def fix_rpath (filepath : Path , libs_relative_path : str ) -> None :
119+ def fix_rpath (filepath : Path , install_rpath : Optional [ str ], libs_rpath : Optional [ str ] ) -> None :
83120 old_rpath = _get_rpath (filepath )
84121 new_rpath = []
85- for path in old_rpath :
86- if path .startswith ('$ORIGIN/' ):
87- path = '$ORIGIN/' + libs_relative_path
88- new_rpath .append (path )
122+ if libs_rpath is not None :
123+ if libs_rpath == '.' :
124+ libs_rpath = ''
125+ for path in old_rpath :
126+ if path .startswith ('$ORIGIN/' ):
127+ new_rpath .append ('$ORIGIN/' + libs_rpath )
128+ if install_rpath :
129+ new_rpath .append (install_rpath )
130+ new_rpath = unique (new_rpath )
89131 if new_rpath != old_rpath :
90132 _set_rpath (filepath , new_rpath )
0 commit comments