From 2269b7f60b2443aa697a5616fcc3692fa3496046 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sat, 15 Jul 2017 05:33:03 -0400 Subject: Add build_rpath as new property allowing people to specify rpath entries that are used in the build tree but will be removed on install. --- mesonbuild/backend/ninjabackend.py | 2 ++ mesonbuild/build.py | 4 ++++ mesonbuild/compilers/c.py | 6 +++--- mesonbuild/compilers/compilers.py | 7 +++++-- mesonbuild/compilers/cs.py | 2 +- mesonbuild/compilers/d.py | 8 +++++--- mesonbuild/compilers/fortran.py | 4 ++-- mesonbuild/compilers/java.py | 2 +- mesonbuild/compilers/rust.py | 4 ++-- mesonbuild/interpreter.py | 1 + mesonbuild/linkers.py | 4 ++-- run_unittests.py | 11 +++++++++++ test cases/unit/11 build_rpath/meson.build | 9 +++++++++ test cases/unit/11 build_rpath/prog.c | 5 +++++ test cases/unit/11 build_rpath/sub/meson.build | 1 + test cases/unit/11 build_rpath/sub/stuff.c | 3 +++ 16 files changed, 57 insertions(+), 16 deletions(-) create mode 100644 test cases/unit/11 build_rpath/meson.build create mode 100644 test cases/unit/11 build_rpath/prog.c create mode 100644 test cases/unit/11 build_rpath/sub/meson.build create mode 100644 test cases/unit/11 build_rpath/sub/stuff.c diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 7f974ee..b134510 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1211,6 +1211,7 @@ int dummy; rpath_args = rustc.build_rpath_args(self.environment.get_build_dir(), target_slashname_workaround_dir, self.determine_rpath_dirs(target), + target.build_rpath, target.install_rpath) # ... but then add rustc's sysroot to account for rustup # installations @@ -2387,6 +2388,7 @@ rule FORTRAN_DEP_HACK commands += linker.build_rpath_args(self.environment.get_build_dir(), target_slashname_workaround_dir, self.determine_rpath_dirs(target), + target.build_rpath, target.install_rpath) # Add libraries generated by custom targets custom_target_libraries = self.get_custom_target_provided_libraries(target) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index fb56cea..e1e1a33 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -49,6 +49,7 @@ known_basic_kwargs = {'install': True, 'gui_app': True, 'extra_files': True, 'install_rpath': True, + 'build_rpath': True, 'resources': True, 'sources': True, 'objects': True, @@ -707,6 +708,9 @@ class BuildTarget(Target): self.install_rpath = kwargs.get('install_rpath', '') if not isinstance(self.install_rpath, str): raise InvalidArguments('Install_rpath is not a string.') + self.build_rpath = kwargs.get('build_rpath', '') + if not isinstance(self.build_rpath, str): + raise InvalidArguments('Build_rpath is not a string.') resources = kwargs.get('resources', []) if not isinstance(resources, list): resources = [resources] diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 593366a..d93c7cc 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -87,8 +87,8 @@ class CCompiler(Compiler): return None, fname # The default behavior is this, override in MSVC - def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath): - return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, install_rpath) + def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): + return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, build_rpath, install_rpath) def get_dependency_gen_args(self, outtarget, outfile): return ['-MMD', '-MQ', outtarget, '-MF', outfile] @@ -909,7 +909,7 @@ class VisualStudioCCompiler(CCompiler): "The name of the outputted import library" return ['/IMPLIB:' + implibname] - def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath): + def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): return [] # FIXME, no idea what these should be. diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 0be3908..c88286c 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -798,8 +798,8 @@ class Compiler: def get_instruction_set_args(self, instruction_set): return None - def build_unix_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath): - if not rpath_paths and not install_rpath: + def build_unix_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): + if not rpath_paths and not install_rpath and not build_rpath: return [] # The rpaths we write must be relative, because otherwise # they have different length depending on the build @@ -812,6 +812,9 @@ class Compiler: relative = os.path.relpath(os.path.join(build_dir, p), os.path.join(build_dir, from_dir)) rel_rpaths.append(relative) paths = ':'.join([os.path.join('$ORIGIN', p) for p in rel_rpaths]) + # Build_rpath is used as-is (it is usually absolute). + if build_rpath != '': + paths += ':' + build_rpath if len(paths) < len(install_rpath): padding = 'X' * (len(install_rpath) - len(paths)) if not paths: diff --git a/mesonbuild/compilers/cs.py b/mesonbuild/compilers/cs.py index e6c5b9e..b8a4d13 100644 --- a/mesonbuild/compilers/cs.py +++ b/mesonbuild/compilers/cs.py @@ -43,7 +43,7 @@ class MonoCompiler(Compiler): def split_shlib_to_parts(self, fname): return None, fname - def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath): + def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): return [] def get_dependency_gen_args(self, outtarget, outfile): diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index e1d534f..a989704 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -88,12 +88,14 @@ class DCompiler(Compiler): def get_std_exe_link_args(self): return [] - def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath): + def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): # This method is to be used by LDC and DMD. # GDC can deal with the verbatim flags. if not rpath_paths and not install_rpath: return [] paths = ':'.join([os.path.join(build_dir, p) for p in rpath_paths]) + if build_rpath != '': + paths += ':' + build_rpath if len(paths) < len(install_rpath): padding = 'X' * (len(install_rpath) - len(paths)) if not paths: @@ -212,8 +214,8 @@ class GnuDCompiler(DCompiler): def get_buildtype_args(self, buildtype): return d_gdc_buildtype_args[buildtype] - def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath): - return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, install_rpath) + def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): + return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, build_rpath, install_rpath) def get_unittest_args(self): return ['-funittest'] diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index d44b529..e17cda0 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -132,8 +132,8 @@ end program prog def get_std_exe_link_args(self): return [] - def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath): - return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, install_rpath) + def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): + return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, build_rpath, install_rpath) def module_name_to_filename(self, module_name): return module_name.lower() + '.mod' diff --git a/mesonbuild/compilers/java.py b/mesonbuild/compilers/java.py index 0253bfe..a8138d7 100644 --- a/mesonbuild/compilers/java.py +++ b/mesonbuild/compilers/java.py @@ -34,7 +34,7 @@ class JavaCompiler(Compiler): def split_shlib_to_parts(self, fname): return None, fname - def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath): + def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): return [] def get_dependency_gen_args(self, outtarget, outfile): diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index 38ba6a2..b93289f 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -50,8 +50,8 @@ class RustCompiler(Compiler): def get_buildtype_args(self, buildtype): return rust_buildtype_args[buildtype] - def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath): - return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, install_rpath) + def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): + return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, build_rpath, install_rpath) def get_sysroot(self): cmd = self.exelist + ['--print', 'sysroot'] diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 359dd17..be3e570 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1241,6 +1241,7 @@ rust_kwargs = set(['rust_crate_type']) cs_kwargs = set(['resources']) buildtarget_kwargs = set(['build_by_default', + 'build_rpath', 'dependencies', 'extra_files', 'gui_app', diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py index d0d5184..e0554e0 100644 --- a/mesonbuild/linkers.py +++ b/mesonbuild/linkers.py @@ -45,7 +45,7 @@ class VisualStudioLinker(StaticLinker): def get_linker_always_args(self): return VisualStudioLinker.always_args - def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath): + def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): return [] def thread_link_flags(self): @@ -76,7 +76,7 @@ class ArLinker(StaticLinker): else: self.std_args = ['csr'] - def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath): + def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): return [] def get_exelist(self): diff --git a/run_unittests.py b/run_unittests.py index 664fdef..875ba65 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -1850,6 +1850,17 @@ class LinuxlikeTests(BasePlatformTests): self.assertTrue(glib_found) self.assertTrue(gobject_found) + def test_build_rpath(self): + testdir = os.path.join(self.unit_test_dir, '11 build_rpath') + self.init(testdir) + self.build() + build_rpath = get_rpath(os.path.join(self.builddir, 'prog')) + self.assertEqual(build_rpath, '$ORIGIN/sub:/foo/bar') + self.install() + install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/prog')) + self.assertEqual(install_rpath, '/baz') + + class LinuxArmCrossCompileTests(BasePlatformTests): ''' Tests that verify cross-compilation to Linux/ARM diff --git a/test cases/unit/11 build_rpath/meson.build b/test cases/unit/11 build_rpath/meson.build new file mode 100644 index 0000000..b84c259 --- /dev/null +++ b/test cases/unit/11 build_rpath/meson.build @@ -0,0 +1,9 @@ +project('build rpath', 'c') + +subdir('sub') +executable('prog', 'prog.c', + link_with : l, + build_rpath : '/foo/bar', + install_rpath : '/baz', + install : true, + ) diff --git a/test cases/unit/11 build_rpath/prog.c b/test cases/unit/11 build_rpath/prog.c new file mode 100644 index 0000000..45b2fa3 --- /dev/null +++ b/test cases/unit/11 build_rpath/prog.c @@ -0,0 +1,5 @@ +int get_stuff(); + +int main(int argc, char **argv) { + return get_stuff(); +} diff --git a/test cases/unit/11 build_rpath/sub/meson.build b/test cases/unit/11 build_rpath/sub/meson.build new file mode 100644 index 0000000..6879ec6 --- /dev/null +++ b/test cases/unit/11 build_rpath/sub/meson.build @@ -0,0 +1 @@ +l = shared_library('stuff', 'stuff.c') diff --git a/test cases/unit/11 build_rpath/sub/stuff.c b/test cases/unit/11 build_rpath/sub/stuff.c new file mode 100644 index 0000000..d56d8b0 --- /dev/null +++ b/test cases/unit/11 build_rpath/sub/stuff.c @@ -0,0 +1,3 @@ +int get_stuff() { + return 0; +} -- cgit v1.1 From e82edc179fe86e68d1f74fe084fd891ef2d12316 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sat, 15 Jul 2017 05:51:45 -0400 Subject: Check for manual attempts to set rpath and update docs. --- docs/markdown/Reference-manual.md | 1 + docs/markdown/Release-notes-for-0.42.0.md | 11 +++++++++++ mesonbuild/build.py | 4 ++++ test cases/linuxlike/7 library versions/meson.build | 14 +++++++++----- 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index 82ea5c2..1e3f640 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -243,6 +243,7 @@ Executable supports the following keyword arguments. Note that just like the pos - `extra_files` are not used for the build itself but are shown as source files in IDEs that group files by targets (such as Visual Studio) - `install`, when set to true, this executable should be installed - `install_rpath` a string to set the target's rpath to after install (but *not* before that) +- `build_rpath` a string to add to target's rpath definition in the build dir, but which will be removed on install - `install_dir` override install directory for this file. The value is relative to the `prefix` specified. F.ex, if you want to install plugins into a subdir, you'd use something like this: `install_dir : get_option('libdir') + '/projectname-1.0'`. - `objects` list of prebuilt object files (usually for third party products you don't have source to) that should be linked in this target, **never** use this for object files that you build yourself. - `name_suffix` the string that will be used as the extension for the target by overriding the default. By default on Windows this is `exe` and on other platforms it is omitted. diff --git a/docs/markdown/Release-notes-for-0.42.0.md b/docs/markdown/Release-notes-for-0.42.0.md index 3374d3b..c8a3305 100644 --- a/docs/markdown/Release-notes-for-0.42.0.md +++ b/docs/markdown/Release-notes-for-0.42.0.md @@ -65,3 +65,14 @@ A new experimental module to compile code with many different SIMD instruction sets and selecting the best one at runtime. This module is unstable, meaning its API is subject to change in later releases. It might also be removed altogether. + +## Added build_rpath keyword argument + +You can specify `build_rpath : '/foo/bar'` in build targets and the +given path will get added to the target's rpath in the build tree. It +is removed during the install step. + +Meson will print a warning when the user tries to add an rpath linker +flag manually, e.g. via `link_args` to a target. This is not +recommended because having multiple rpath causes them to stomp on each +other. This warning will become a hard error in some future release. diff --git a/mesonbuild/build.py b/mesonbuild/build.py index e1e1a33..99e132d 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -670,6 +670,10 @@ class BuildTarget(Target): for i in self.link_args: if not isinstance(i, str): raise InvalidArguments('Link_args arguments must be strings.') + for l in self.link_args: + if '-Wl,-rpath' in l or l.startswith('-rpath'): + mlog.warning('''Please do not define rpath with a linker argument, use install_rpath or build_rpath properties instead. +This will become a hard error in a future Meson release.''') self.process_link_depends(kwargs.get('link_depends', []), environment) # Target-specific include dirs must be added BEFORE include dirs from # internal deps (added inside self.add_deps()) to override them. diff --git a/test cases/linuxlike/7 library versions/meson.build b/test cases/linuxlike/7 library versions/meson.build index d156eb0..5160947 100644 --- a/test cases/linuxlike/7 library versions/meson.build +++ b/test cases/linuxlike/7 library versions/meson.build @@ -32,20 +32,24 @@ out = custom_target('library-dependency-hack', # Need to add this manually because Meson can't add it automatically because # it doesn't know that we are linking to libraries in the build directory. -rpath_arg = '-Wl,-rpath,' + meson.current_build_dir() +rpath_dir = meson.current_build_dir() # Manually test if the linker can find the above libraries # i.e., whether they were generated with the right naming scheme test('manually linked 1', executable('manuallink1', out, - link_args : ['-L.', '-lsome', rpath_arg])) + link_args : ['-L.', '-lsome'], + build_rpath : rpath_dir)) test('manually linked 2', executable('manuallink2', out, - link_args : ['-L.', '-lnoversion', rpath_arg])) + link_args : ['-L.', '-lnoversion'], + build_rpath : rpath_dir)) test('manually linked 3', executable('manuallink3', out, - link_args : ['-L.', '-lonlyversion', rpath_arg])) + link_args : ['-L.', '-lonlyversion'], + build_rpath : rpath_dir)) test('manually linked 4', executable('manuallink4', out, - link_args : ['-L.', '-lonlysoversion', rpath_arg])) + link_args : ['-L.', '-lonlysoversion'], + build_rpath : rpath_dir)) shared_module('module', 'lib.c', install : true) -- cgit v1.1