Skip to content

Commit ab69985

Browse files
committed
Be more precise about what a runtime_file is
For versioned libraries, it's now always the file that the dynamic loader will load (e.g. the soname).
1 parent cd6ee63 commit ab69985

4 files changed

Lines changed: 66 additions & 6 deletions

File tree

‎bfg9000/builtins/install.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ def _add_implicit(self, item, directory):
3636
self.host[src] = h
3737
self.target[src] = t
3838

39-
for dep in src.install_deps:
40-
self._add_implicit(dep, directory)
39+
for dep in src.install_deps:
40+
self._add_implicit(dep, directory)
4141

4242
return target
4343

‎bfg9000/file_types.py‎

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,15 +276,31 @@ def __init__(self, path, library, **kwargs):
276276

277277
@property
278278
def runtime_file(self):
279-
return self.library
279+
return self.library.runtime_file
280+
281+
282+
class LoadLibrary(LinkLibrary):
283+
def __init__(self, *args, **kwargs):
284+
super().__init__(*args, **kwargs)
285+
self.runtime_deps = [self.library]
286+
287+
@property
288+
def runtime_file(self):
289+
return self
280290

281291

282292
class VersionedSharedLibrary(SharedLibrary):
283293
def __init__(self, path, format, lang, soname_path, linkname_path,
284294
**kwargs):
285295
super().__init__(path, format, lang, **kwargs)
286-
self.soname = LinkLibrary(soname_path, self, parent=self)
296+
self.soname = LoadLibrary(soname_path, self, parent=self)
287297
self.link = LinkLibrary(linkname_path, self.soname, parent=self)
298+
# At runtime, the loader will look for the soname for this library.
299+
self.runtime_deps = [self.soname]
300+
301+
@property
302+
def runtime_file(self):
303+
return self.soname
288304

289305

290306
class StaticLibrary(Library):
@@ -322,6 +338,10 @@ def __init__(self, path, format, lang, import_path, export_path=None, *,
322338
self.export_file = (ExportFile(export_path, parent=self)
323339
if export_path else None)
324340

341+
@property
342+
def runtime_file(self):
343+
return self
344+
325345

326346
class DualUseLibrary(BaseFile):
327347
def __init__(self, shared, static):

‎test/unit/test_file_types.py‎

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,19 @@ def test_clone_recursive(self):
226226
LinkLibrary(Path('a'), dstlib), recursive=True)
227227

228228

229+
class TestLoadLibrary(FileTest):
230+
def test_clone(self):
231+
lib = SharedLibrary(Path('a.so', Root.srcdir), 'elf', 'c')
232+
self.assertClone(LoadLibrary(Path('a', Root.srcdir), lib),
233+
LoadLibrary(Path('a'), lib))
234+
235+
def test_clone_recursive(self):
236+
srclib = SharedLibrary(Path('a.so', Root.srcdir), 'elf', 'c')
237+
dstlib = SharedLibrary(Path('a.so'), 'elf', 'c')
238+
self.assertClone(LoadLibrary(Path('a', Root.srcdir), srclib),
239+
LoadLibrary(Path('a'), dstlib), recursive=True)
240+
241+
229242
class TestVersionedSharedLibrary(FileTest):
230243
def test_clone(self):
231244
src = VersionedSharedLibrary(
@@ -236,12 +249,14 @@ def test_clone(self):
236249
Path('a.1.2.3'), 'elf', 'c',
237250
Path('a.1', Root.srcdir), Path('a', Root.srcdir)
238251
)
239-
dst.soname.library = dst.soname.linktime_deps[0] = src
252+
dst.soname.library = src
253+
dst.soname.runtime_deps[0] = dst.soname.linktime_deps[0] = src
240254
dst.link.library = dst.link.linktime_deps[0] = src.soname
241255
dst.soname.parent = dst.link.parent = src
256+
dst.runtime_deps[0] = src.soname
242257
self.assertClone(src, dst)
243258

244-
dst_soname = LinkLibrary(Path('a.1'), src)
259+
dst_soname = LoadLibrary(Path('a.1'), src)
245260
self.assertClone(src.soname, dst_soname)
246261

247262
dst_link = LinkLibrary(Path('a'), src.soname)

‎test/unit/tools/cc/test_linker.py‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from bfg9000.tools.cc import CcBuilder
1212
from bfg9000.packages import Framework
1313
from bfg9000.path import abspath, InstallRoot, Path, Root
14+
from bfg9000.versioning import Version
1415

1516

1617
class TestCcLinker(CrossPlatformTestCase):
@@ -100,6 +101,8 @@ def test_flags_lib_dir(self):
100101
lib = self.Path('/path/to/lib/libfoo.a')
101102
srclibdir = self.Path('.', Root.srcdir)
102103
srclib = self.Path('libfoo.a', Root.srcdir)
104+
srcverlib = self.Path('libfoo.so.1.2.3', Root.srcdir)
105+
srcsoname = self.Path('libfoo.so.1', Root.srcdir)
103106

104107
if self.shared:
105108
output = SharedLibrary(self.Path('out'), 'native')
@@ -134,6 +137,12 @@ def test_flags_lib_dir(self):
134137
opts.lib(SharedLibrary(srclib, 'native'))
135138
), output=output), ['-L' + srclibdir] + srcdir_rpath + soname)
136139

140+
# Versioned library
141+
self.assertEqual(self.linker.flags(opts.option_list(
142+
opts.lib(VersionedSharedLibrary(srcverlib, 'native', 'c',
143+
srcsoname, srclib))
144+
), output=output), ['-L' + srclibdir] + srcdir_rpath + soname)
145+
137146
if self.env.target_platform.genus == 'linux':
138147
libdir2 = self.Path('foo')
139148
lib2 = self.Path('foo/libbar.a')
@@ -149,6 +158,22 @@ def test_flags_lib_dir(self):
149158
['-L' + libdir2, '-Wl,-rpath,$ORIGIN/foo'] + soname
150159
)
151160

161+
# Make sure we handle rpath-link for broken BFD-based ld. See
162+
# `bfg9000/tools/cc/linker.py`
163+
class BrokenBfdLinker:
164+
brand = 'bfd'
165+
version = Version('2.27')
166+
with mock.patch('bfg9000.tools.cc.CcBuilder.linker',
167+
return_value=BrokenBfdLinker()):
168+
s = SharedLibrary(srclib, 'native')
169+
s.runtime_deps = [SharedLibrary(lib2, 'native')]
170+
self.assertEqual(
171+
self.linker.flags(opts.option_list(opts.lib(s)),
172+
output=output),
173+
(['-L' + srclibdir] + srcdir_rpath +
174+
['-Wl,-rpath-link,' + libdir2] + soname)
175+
)
176+
152177
# Static library
153178
self.assertEqual(self.linker.flags(opts.option_list(
154179
opts.lib(StaticLibrary(lib, 'native'))

0 commit comments

Comments
 (0)