Skip to content

Commit d56a28a

Browse files
committed
[WIP] Restore suport for @rpath on macOS
1 parent cd6ee63 commit d56a28a

3 files changed

Lines changed: 50 additions & 36 deletions

File tree

‎bfg9000/tools/cc/linker.py‎

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -119,33 +119,44 @@ def _always_flags(self):
119119
return []
120120

121121
def _local_rpath(self, library, output):
122-
if ( not isinstance(library, Library) or
123-
self.builder.object_format != 'elf' ):
122+
if not isinstance(library, Library):
124123
return None, []
125-
126-
rpath = patchelf.local_rpath(self.env, library, output)
127-
if rpath is None:
124+
elif self.builder.object_format == 'elf':
125+
rpath = patchelf.local_rpath(self.env, library, output)
126+
if rpath is None:
127+
return None, []
128+
129+
# Prior to binutils 2.28, GNU's BFD-based ld doesn't correctly
130+
# respect $ORIGIN in a shared library's DT_RPATH/DT_RUNPATH field.
131+
# This results in ld being unable to find other shared libraries
132+
# needed by the directly-linked library. For more information, see:
133+
# <https://sourceware.org/bugzilla/show_bug.cgi?id=20535>.
134+
try:
135+
ld = self.builder.linker('raw')
136+
fix_rpath = (ld.brand == 'bfd' and ld.version in
137+
SpecifierSet('<2.28'))
138+
except KeyError:
139+
fix_rpath = False
140+
141+
rpath_link = []
142+
if output and fix_rpath:
143+
rpath_link = [
144+
i.path.parent() for i in
145+
recursive_walk(library.runtime_file, 'runtime_deps')
146+
]
147+
148+
return rpath, rpath_link
149+
elif self.builder.object_format == 'mach-o':
150+
if not library.runtime_file:
151+
return None, []
152+
rpath = Path('.', library.runtime_file.path.root).cross(self.env)
153+
if rpath.root == output.path.root:
154+
rpath = rpath.relpath(output.path.parent(),
155+
prefix='@loader_path')
156+
return rpath, []
157+
else:
128158
return None, []
129159

130-
# Prior to binutils 2.28, GNU's BFD-based ld doesn't correctly respect
131-
# $ORIGIN in a shared library's DT_RPATH/DT_RUNPATH field. This results
132-
# in ld being unable to find other shared libraries needed by the
133-
# directly-linked library. For more information, see:
134-
# <https://sourceware.org/bugzilla/show_bug.cgi?id=20535>.
135-
try:
136-
ld = self.builder.linker('raw')
137-
fix_rpath = (ld.brand == 'bfd' and ld.version in
138-
SpecifierSet('<2.28'))
139-
except KeyError:
140-
fix_rpath = False
141-
142-
rpath_link = []
143-
if output and fix_rpath:
144-
rpath_link = [i.path.parent() for i in
145-
recursive_walk(library.runtime_file, 'runtime_deps')]
146-
147-
return rpath, rpath_link
148-
149160
def always_libs(self, primary):
150161
# XXX: Don't just asssume that these are the right libraries to use.
151162
# For instance, clang users might want to use libc++ instead.
@@ -280,8 +291,13 @@ def flags(self, options, global_options=None, output=None, mode='normal'):
280291

281292
flags.extend('-L' + i for i in uniques(lib_dirs))
282293
if rpaths:
283-
flags.append('-Wl,-rpath,' + safe_str.join(rpaths, ':'))
294+
rpaths = uniques(rpaths)
295+
if self.builder.linker('raw').brand == 'apple':
296+
flags.extend('-Wl,-rpath,{}'.format(i) for i in rpaths)
297+
else:
298+
flags.append('-Wl,-rpath,' + safe_str.join(rpaths, ':'))
284299
if rpath_links:
300+
rpath_links = uniques(rpath_links)
285301
flags.append('-Wl,-rpath-link,' + safe_str.join(rpath_links, ':'))
286302
return flags
287303

‎bfg9000/tools/install_name_tool.py‎

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import os
2+
13
from . import tool
24
from .. import file_types, options as opts
35
from .common import SimpleCommand
@@ -25,18 +27,13 @@ def _call(self, cmd, file, *, id=None, changes=[]):
2527

2628

2729
def darwin_install_name(library, env, strict=True):
28-
while isinstance(library, file_types.LinkLibrary):
29-
library = library.library
30-
31-
if isinstance(library, file_types.VersionedSharedLibrary):
32-
return library.soname.path.string(env.base_dirs)
33-
elif isinstance(library, file_types.SharedLibrary):
34-
return library.path.string(env.base_dirs)
35-
elif strict: # pragma: no cover
36-
raise TypeError('unable to create darwin install_name')
37-
else:
30+
if isinstance(library, file_types.SharedLibrary):
31+
return os.path.join('@rpath', library.runtime_file.path.suffix)
32+
elif not strict:
3833
return None
3934

35+
raise TypeError('unable to create darwin install_name') # pragma: no cover
36+
4037

4138
def post_install(env, options, output, install_db, *, is_library=False):
4239
change_opts = options.filter(opts.install_name_change)

‎bfg9000/tools/pkg_config.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,8 @@ def link_options(self, linker, *, raw=False):
235235
# should check if there are any install_names set that we need
236236
# to update when installing. For more information, see the
237237
# pkg-config builtin.
238-
extra_opts = self._get_install_name_changes()
238+
extra_opts = (self._get_rpaths() +
239+
self._get_install_name_changes())
239240

240241
return flags + libdirs + libs + extra_opts
241242

0 commit comments

Comments
 (0)