From 3673791b4f7d8fbc290629b1173fff91d7aee781 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Fri, 4 Oct 2013 23:04:26 +0300 Subject: [PATCH] Rpaths start working. --- backends.py | 3 +- build.py | 14 +++++++- depfixer.py | 33 ++++++++++++++++--- environment.py | 18 ++++++++++ test cases/common/46 library chain/main.c | 5 +++ .../common/46 library chain/meson.build | 5 +++ .../common/46 library chain/subdir/lib1.c | 6 ++++ .../46 library chain/subdir/meson.build | 4 +++ .../46 library chain/subdir/subdir2/lib2.c | 3 ++ .../subdir/subdir2/meson.build | 1 + .../46 library chain/subdir/subdir3/lib3.c | 3 ++ .../subdir/subdir3/meson.build | 1 + 12 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 test cases/common/46 library chain/main.c create mode 100644 test cases/common/46 library chain/meson.build create mode 100644 test cases/common/46 library chain/subdir/lib1.c create mode 100644 test cases/common/46 library chain/subdir/meson.build create mode 100644 test cases/common/46 library chain/subdir/subdir2/lib2.c create mode 100644 test cases/common/46 library chain/subdir/subdir2/meson.build create mode 100644 test cases/common/46 library chain/subdir/subdir3/lib3.c create mode 100644 test cases/common/46 library chain/subdir/subdir3/meson.build diff --git a/backends.py b/backends.py index b471d5119..32c227022 100644 --- a/backends.py +++ b/backends.py @@ -225,7 +225,6 @@ class Backend(): if compiler.id == 'msvc': if fname.endswith('dll'): fname = fname[:-3] + 'lib' - fname = os.path.join('.', fname) # Hack to make ldd find the library. args.append(fname) return args @@ -852,6 +851,7 @@ class NinjaBackend(Backend): elif isinstance(target, build.SharedLibrary): commands += linker.get_std_shared_lib_link_flags() commands += linker.get_pic_flags() + commands += linker.get_soname_flags(target.name) elif isinstance(target, build.StaticLibrary): commands += linker.get_std_link_flags() else: @@ -860,6 +860,7 @@ class NinjaBackend(Backend): commands += dep.get_link_flags() dependencies = target.get_dependencies() commands += self.build_target_link_arguments(linker, dependencies) + commands.append(linker.build_rpath_arg(self.environment.get_build_dir(), target.get_rpaths())) if self.environment.coredata.coverage: commands += linker.get_coverage_link_flags() dep_targets = [self.get_dependency_filename(t) for t in dependencies] diff --git a/build.py b/build.py index 67d130380..64125a88a 100644 --- a/build.py +++ b/build.py @@ -108,7 +108,7 @@ class BuildTarget(): self.process_kwargs(kwargs) if len(self.sources) == 0 and len(self.generated) == 0: raise InvalidArguments('Build target %s has no sources.' % name) - + def process_sourcelist(self, sources): if not isinstance(sources, list): sources = [sources] @@ -143,6 +143,15 @@ class BuildTarget(): newd.append(i) self.kwargs['deps'] = newd + def get_rpaths(self): + return self.get_transitive_rpaths() + + def get_transitive_rpaths(self): + result = [] + for i in self.link_targets: + result += i.get_rpaths() + return result + def process_kwargs(self, kwargs): self.copy_kwargs(kwargs) kwargs.get('modules', []) @@ -404,6 +413,9 @@ class SharedLibrary(BuildTarget): def get_shbase(self): return self.prefix + self.name + '.' + self.suffix + def get_rpaths(self): + return [self.subdir] + self.get_transitive_rpaths() + def get_filename(self): fname = self.get_shbase() if self.version is None: diff --git a/depfixer.py b/depfixer.py index 026fc30af..c93d58c5b 100755 --- a/depfixer.py +++ b/depfixer.py @@ -187,6 +187,17 @@ class Elf(): self.bf.seek(strtab.val + soname.val) print(self.read_str()) + def get_rpath_offset(self): + sec = self.find_section(b'.dynstr') + for i in self.dynamic: + if i.d_tag == DT_RPATH: + rpath = i + return sec.sh_offset + rpath.val + + def print_rpath(self): + self.bf.seek(self.get_rpath_offset()) + print(self.read_str()) + def print_deps(self): sec = self.find_section(b'.dynstr') deps = [] @@ -217,14 +228,26 @@ class Elf(): self.bf.seek(offset) self.bf.write(newname) + def fix_rpath(self, new_rpath): + rp_off = self.get_rpath_offset() + self.bf.seek(rp_off) + old_rpath = self.read_str() + if len(old_rpath) < len(new_rpath): + print("New rpath must not be longer than the old one.") + self.bf.seek(rp_off) + self.bf.write(new_rpath) + self.bf.write(b'\0'*(len(old_rpath) - len(new_rpath) + 1)) if __name__ == '__main__': - if len(sys.argv) != 3: - print('This application converts absolute dep paths to relative ones.') + if len(sys.argv) < 2 or len(sys.argv) > 3: + print('This application resets target rpath.') print('Don\'t run this unless you know what you are doing.') print('%s: ' % sys.argv[0]) exit(1) e = Elf(sys.argv[1]) - prefix = sys.argv[2] - #e.print_deps() - e.fix_deps(prefix.encode()) + if len(sys.argv) == 2: + e.print_rpath() + else: + new_rpath = sys.argv[2] + e.fix_rpath(new_rpath.encode('utf8')) + #e.fix_deps(prefix.encode()) diff --git a/environment.py b/environment.py index e6d21afbb..0e67499cb 100644 --- a/environment.py +++ b/environment.py @@ -56,6 +56,15 @@ class CCompiler(): def get_always_flags(self): return [] + def get_soname_flags(self, shlib_name): + return [] + + def split_shlib_to_parts(self, fname): + return (None, fname) + + def build_rpath_arg(self, build_dir, rpath_paths): + return '' + def get_id(self): return self.id @@ -503,6 +512,15 @@ class GnuCCompiler(CCompiler): def get_pch_suffix(self): return 'gch' + def split_shlib_to_parts(self, fname): + return (os.path.split(fname)[0], fname) + + def build_rpath_arg(self, build_dir, rpath_paths): + return '-Wl,-rpath,' + ':'.join([os.path.join(build_dir, p) for p in rpath_paths]) + + def get_soname_flags(self, shlib_name): + return ['-Wl,-soname,lib%s.so' % shlib_name] + class GnuObjCCompiler(ObjCCompiler): std_warn_flags = ['-Wall', '-Winvalid-pch'] std_opt_flags = ['-O2'] diff --git a/test cases/common/46 library chain/main.c b/test cases/common/46 library chain/main.c new file mode 100644 index 000000000..7b015b712 --- /dev/null +++ b/test cases/common/46 library chain/main.c @@ -0,0 +1,5 @@ +int libfun(); + +int main() { + return libfun(); +} diff --git a/test cases/common/46 library chain/meson.build b/test cases/common/46 library chain/meson.build new file mode 100644 index 000000000..c22b9ccb8 --- /dev/null +++ b/test cases/common/46 library chain/meson.build @@ -0,0 +1,5 @@ +project('libchain', 'c') + +subdir('subdir') +e = executable('prog', 'main.c', link_with : lib1) +test('tst', e) diff --git a/test cases/common/46 library chain/subdir/lib1.c b/test cases/common/46 library chain/subdir/lib1.c new file mode 100644 index 000000000..a1fd5bc6f --- /dev/null +++ b/test cases/common/46 library chain/subdir/lib1.c @@ -0,0 +1,6 @@ +int lib2fun(); +int lib3fun(); + +int libfun() { + return lib2fun() + lib3fun(); +} diff --git a/test cases/common/46 library chain/subdir/meson.build b/test cases/common/46 library chain/subdir/meson.build new file mode 100644 index 000000000..80c68067c --- /dev/null +++ b/test cases/common/46 library chain/subdir/meson.build @@ -0,0 +1,4 @@ +subdir('subdir2') +subdir('subdir3') + +lib1 = shared_library('lib1', 'lib1.c', link_with : [lib2, lib3]) diff --git a/test cases/common/46 library chain/subdir/subdir2/lib2.c b/test cases/common/46 library chain/subdir/subdir2/lib2.c new file mode 100644 index 000000000..490e44463 --- /dev/null +++ b/test cases/common/46 library chain/subdir/subdir2/lib2.c @@ -0,0 +1,3 @@ +int lib2fun() { + return 0; +} diff --git a/test cases/common/46 library chain/subdir/subdir2/meson.build b/test cases/common/46 library chain/subdir/subdir2/meson.build new file mode 100644 index 000000000..178b33d36 --- /dev/null +++ b/test cases/common/46 library chain/subdir/subdir2/meson.build @@ -0,0 +1 @@ +lib2 = shared_library('lib2', 'lib2.c') diff --git a/test cases/common/46 library chain/subdir/subdir3/lib3.c b/test cases/common/46 library chain/subdir/subdir3/lib3.c new file mode 100644 index 000000000..fed00d541 --- /dev/null +++ b/test cases/common/46 library chain/subdir/subdir3/lib3.c @@ -0,0 +1,3 @@ +int lib3fun() { + return 0; +} diff --git a/test cases/common/46 library chain/subdir/subdir3/meson.build b/test cases/common/46 library chain/subdir/subdir3/meson.build new file mode 100644 index 000000000..21f1d6e49 --- /dev/null +++ b/test cases/common/46 library chain/subdir/subdir3/meson.build @@ -0,0 +1 @@ +lib3 = shared_library('lib3', 'lib3.c')