[libvirt PATCH 0/2] meson: Introduce rpath option

See 1/2 for details. Andrea Bolognani (2): meson: Introduce rpath option spec: Disable RPATH libvirt.spec.in | 1 + meson.build | 7 + meson_options.txt | 1 + src/meson.build | 485 +++++++++++++++++++++++++++++++--------------- tools/meson.build | 332 ++++++++++++++++++++----------- 5 files changed, 567 insertions(+), 259 deletions(-) -- 2.26.2

Right now we're unconditionally adding RPATH information to the installed binaries and libraries, but that's not always desired. Debian explicitly passes --disable-rpath to configure, and while I haven't been able to find the same option in the spec file for either Fedora or RHEL, by running $ readelf -d /usr/bin/virsh | grep PATH I can see that the information is not present, so I assume they also strip it somehow. Both Debian and Fedora have wiki pages encouraging packagers to avoid setting RPATH: https://wiki.debian.org/RpathIssue https://fedoraproject.org/wiki/RPath_Packaging_Draft Given the above I'm not actually sure whether there even is a valid usecase for RPATH, but I will openly admit I don't understand the problem space well enough to pass judgement. So, assuming there are scenarios where we want RPATH information to be present, our only course of action is making its inclusion configurable, just like it was with autotools. This commit introduces the 'rpath' option, which is enabled by default and can be turned off to avoid including RPATH information in the distributed binaries and libraries. The implementation is pretty naive and arguably verging on unmaintainable, but unfortunately I lack the Meson-fu necessary to do any better than this. Thankfully we have developers on the list who are well versed in the build system and will certainly come up with a reasonable solution :) This commit is better viewed with 'git show -w'. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- meson.build | 7 + meson_options.txt | 1 + src/meson.build | 485 +++++++++++++++++++++++++++++++--------------- tools/meson.build | 332 ++++++++++++++++++++----------- 4 files changed, 566 insertions(+), 259 deletions(-) diff --git a/meson.build b/meson.build index a72d0c0e85..bc050a63e2 100644 --- a/meson.build +++ b/meson.build @@ -156,6 +156,13 @@ if rc.returncode() == 0 endif +# whether to enable rpath + +if get_option('rpath') + conf.set_quoted('RPATH', libdir) +endif + + # figure out libvirt version strings arr_version = meson.project_version().split('.') diff --git a/meson_options.txt b/meson_options.txt index c538d323c1..71d81304bc 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -6,6 +6,7 @@ option('runstatedir', type: 'string', value: '', description: 'State directory f option('expensive_tests', type: 'feature', value: 'auto', description: 'set the default for enabling expensive tests (long timeouts), use VIR_TEST_EXPENSIVE to override') option('test_coverage', type: 'boolean', value: false, description: 'turn on code coverage instrumentation') option('git_werror', type: 'feature', value: 'auto', description: 'use -Werror if building from GIT') +option('rpath', type: 'boolean', value: true, description: 'add rpath information to installed binaries and libraries') # build dependencies options diff --git a/src/meson.build b/src/meson.build index 73ac99f01e..876f954df3 100644 --- a/src/meson.build +++ b/src/meson.build @@ -437,27 +437,50 @@ libvirt_qemu_sources = files( 'libvirt-qemu.c', ) -libvirt_qemu_lib = shared_library( - 'virt-qemu', - libvirt_qemu_sources, - dependencies: [ - src_dep, - ], - link_args: [ - libvirt_nodelete, - libvirt_qemu_syms_flags, - ], - link_with: [ - libvirt_lib, - ], - link_depends: [ - libvirt_qemu_syms_file, - ], - install: true, - install_rpath: libdir, - version: libvirt_lib_version, - soversion: libvirt_so_version, -) +if conf.has('RPATH') + libvirt_qemu_lib = shared_library( + 'virt-qemu', + libvirt_qemu_sources, + dependencies: [ + src_dep, + ], + link_args: [ + libvirt_nodelete, + libvirt_qemu_syms_flags, + ], + link_with: [ + libvirt_lib, + ], + link_depends: [ + libvirt_qemu_syms_file, + ], + install: true, + install_rpath: conf.get('RPATH'), + version: libvirt_lib_version, + soversion: libvirt_so_version, + ) +else + libvirt_qemu_lib = shared_library( + 'virt-qemu', + libvirt_qemu_sources, + dependencies: [ + src_dep, + ], + link_args: [ + libvirt_nodelete, + libvirt_qemu_syms_flags, + ], + link_with: [ + libvirt_lib, + ], + link_depends: [ + libvirt_qemu_syms_file, + ], + install: true, + version: libvirt_lib_version, + soversion: libvirt_so_version, + ) +endif # libvirt-lxc.so symbol files @@ -491,178 +514,338 @@ libvirt_lxc_sources = files( 'libvirt-lxc.c', ) -libvirt_lxc_lib = shared_library( - 'virt-lxc', - libvirt_lxc_sources, - dependencies: [ - apparmor_dep, - selinux_dep, - src_dep, - ], - link_args: [ - libvirt_nodelete, - libvirt_lxc_syms_flags, - ], - link_with: [ - libvirt_lib, - ], - link_depends: [ - libvirt_lxc_syms_file, - ], - install: true, - install_rpath: libdir, - version: libvirt_lib_version, - soversion: libvirt_so_version, -) - - -# libvirt-admin.so - -libvirt_admin_lib = shared_library( - 'virt-admin', - [ - admin_sources, - admin_client_generated, - admin_driver_generated, - datatypes_sources, - dtrace_gen_objects, - ], - dependencies: [ - capng_dep, - devmapper_dep, - gnutls_dep, - libssh2_dep, - libssh_dep, - sasl_dep, - src_dep, - rpc_dep, - xdr_dep, - yajl_dep, - ], - include_directories: [ - admin_inc_dir, - remote_inc_dir, - ], - link_args: [ - libvirt_admin_syms_flags, - libvirt_nodelete, - ], - link_with: [ - libvirt_lib, - ], - link_depends: [ - libvirt_admin_syms_file, - ], - install: true, - install_rpath: libdir, - version: libvirt_lib_version, - soversion: libvirt_so_version, -) - - -# build libvirt shared modules - -foreach module : virt_modules - mod = shared_module( - module['name'], - module.get('sources', []), - name_prefix: module.get('name_prefix', 'lib'), - include_directories: [ - conf_inc_dir, - module.get('include', []), - ], +if conf.has('RPATH') + libvirt_lxc_lib = shared_library( + 'virt-lxc', + libvirt_lxc_sources, dependencies: [ + apparmor_dep, + selinux_dep, src_dep, - module.get('deps', []), - ], + ], + link_args: [ + libvirt_nodelete, + libvirt_lxc_syms_flags, + ], link_with: [ libvirt_lib, - module.get('link_with', []), - ], - link_whole: [ - module.get('link_whole', []), - ], + ], + link_depends: [ + libvirt_lxc_syms_file, + ], + install: true, + install_rpath: conf.get('RPATH'), + version: libvirt_lib_version, + soversion: libvirt_so_version, + ) +else + libvirt_lxc_lib = shared_library( + 'virt-lxc', + libvirt_lxc_sources, + dependencies: [ + apparmor_dep, + selinux_dep, + src_dep, + ], link_args: [ libvirt_nodelete, - module.get('link_args', []), - ], + libvirt_lxc_syms_flags, + ], + link_with: [ + libvirt_lib, + ], + link_depends: [ + libvirt_lxc_syms_file, + ], install: true, - install_dir: module.get('install_dir', libdir / 'libvirt' / 'connection-driver'), - install_rpath: libdir, - ) - set_variable('@0@_module'.format(module['name'].underscorify()), mod) -endforeach + version: libvirt_lib_version, + soversion: libvirt_so_version, + ) +endif -# build libvirt daemons +# libvirt-admin.so -foreach daemon : virt_daemons - bin = executable( - daemon['name'], +if conf.has('RPATH') + libvirt_admin_lib = shared_library( + 'virt-admin', [ - daemon.get('sources', [ remote_daemon_sources, remote_daemon_generated ]), + admin_sources, + admin_client_generated, + admin_driver_generated, + datatypes_sources, dtrace_gen_objects, - ], - c_args: [ - daemon.get('c_args', []), - ], + ], + dependencies: [ + capng_dep, + devmapper_dep, + gnutls_dep, + libssh2_dep, + libssh_dep, + sasl_dep, + src_dep, + rpc_dep, + xdr_dep, + yajl_dep, + ], include_directories: [ - conf_inc_dir, + admin_inc_dir, remote_inc_dir, - daemon.get('include', []), - ], + ], + link_args: [ + libvirt_admin_syms_flags, + libvirt_nodelete, + ], + link_with: [ + libvirt_lib, + ], + link_depends: [ + libvirt_admin_syms_file, + ], + install: true, + install_rpath: conf.get('RPATH'), + version: libvirt_lib_version, + soversion: libvirt_so_version, + ) +else + libvirt_admin_lib = shared_library( + 'virt-admin', + [ + admin_sources, + admin_client_generated, + admin_driver_generated, + datatypes_sources, + dtrace_gen_objects, + ], dependencies: [ - admin_dep, - access_dep, - dbus_dep, + capng_dep, + devmapper_dep, gnutls_dep, - libnl_dep, - rpc_dep, - src_dep, + libssh2_dep, + libssh_dep, sasl_dep, + src_dep, + rpc_dep, xdr_dep, - ], + yajl_dep, + ], + include_directories: [ + admin_inc_dir, + remote_inc_dir, + ], + link_args: [ + libvirt_admin_syms_flags, + libvirt_nodelete, + ], link_with: [ - admin_driver_lib, libvirt_lib, - libvirt_lxc_lib, - libvirt_qemu_lib, - ], - link_args: [ - libvirt_no_undefined, - ], + ], + link_depends: [ + libvirt_admin_syms_file, + ], install: true, - install_dir: sbindir, - install_rpath: libdir, - ) + version: libvirt_lib_version, + soversion: libvirt_so_version, + ) +endif + + +# build libvirt shared modules + +foreach module : virt_modules + if conf.has('RPATH') + mod = shared_module( + module['name'], + module.get('sources', []), + name_prefix: module.get('name_prefix', 'lib'), + include_directories: [ + conf_inc_dir, + module.get('include', []), + ], + dependencies: [ + src_dep, + module.get('deps', []), + ], + link_with: [ + libvirt_lib, + module.get('link_with', []), + ], + link_whole: [ + module.get('link_whole', []), + ], + link_args: [ + libvirt_nodelete, + module.get('link_args', []), + ], + install: true, + install_dir: module.get('install_dir', libdir / 'libvirt' / 'connection-driver'), + install_rpath: conf.get('RPATH'), + ) + else + mod = shared_module( + module['name'], + module.get('sources', []), + name_prefix: module.get('name_prefix', 'lib'), + include_directories: [ + conf_inc_dir, + module.get('include', []), + ], + dependencies: [ + src_dep, + module.get('deps', []), + ], + link_with: [ + libvirt_lib, + module.get('link_with', []), + ], + link_whole: [ + module.get('link_whole', []), + ], + link_args: [ + libvirt_nodelete, + module.get('link_args', []), + ], + install: true, + install_dir: module.get('install_dir', libdir / 'libvirt' / 'connection-driver'), + ) + endif + set_variable('@0@_module'.format(module['name'].underscorify()), mod) +endforeach + + +# build libvirt daemons + +foreach daemon : virt_daemons + if conf.has('RPATH') + bin = executable( + daemon['name'], + [ + daemon.get('sources', [ remote_daemon_sources, remote_daemon_generated ]), + dtrace_gen_objects, + ], + c_args: [ + daemon.get('c_args', []), + ], + include_directories: [ + conf_inc_dir, + remote_inc_dir, + daemon.get('include', []), + ], + dependencies: [ + admin_dep, + access_dep, + dbus_dep, + gnutls_dep, + libnl_dep, + rpc_dep, + src_dep, + sasl_dep, + xdr_dep, + ], + link_with: [ + admin_driver_lib, + libvirt_lib, + libvirt_lxc_lib, + libvirt_qemu_lib, + ], + link_args: [ + libvirt_no_undefined, + ], + install: true, + install_dir: sbindir, + install_rpath: conf.get('RPATH'), + ) + else + bin = executable( + daemon['name'], + [ + daemon.get('sources', [ remote_daemon_sources, remote_daemon_generated ]), + dtrace_gen_objects, + ], + c_args: [ + daemon.get('c_args', []), + ], + include_directories: [ + conf_inc_dir, + remote_inc_dir, + daemon.get('include', []), + ], + dependencies: [ + admin_dep, + access_dep, + dbus_dep, + gnutls_dep, + libnl_dep, + rpc_dep, + src_dep, + sasl_dep, + xdr_dep, + ], + link_with: [ + admin_driver_lib, + libvirt_lib, + libvirt_lxc_lib, + libvirt_qemu_lib, + ], + link_args: [ + libvirt_no_undefined, + ], + install: true, + install_dir: sbindir, + ) +endif endforeach # build libvirt helpers foreach helper : virt_helpers + if conf.has('RPATH') + bin = executable( + helper['name'], + [ + helper['sources'], + ], + c_args: [ + helper.get('c_args', []), + ], + include_directories: [ + helper.get('include', []), + ], + dependencies: [ + src_dep, + helper.get('deps', []), + ], + link_with: [ + libvirt_lib, + ], + install: true, + install_dir: helper.get('install_dir', libexecdir), + install_rpath: conf.get('RPATH'), + ) +else bin = executable( helper['name'], [ helper['sources'], - ], + ], c_args: [ helper.get('c_args', []), - ], + ], include_directories: [ helper.get('include', []), - ], + ], dependencies: [ src_dep, helper.get('deps', []), - ], + ], link_with: [ libvirt_lib, - ], + ], install: true, install_dir: helper.get('install_dir', libexecdir), - install_rpath: libdir, - ) + ) +endif endforeach diff --git a/tools/meson.build b/tools/meson.build index 090179470a..d50ee94f30 100644 --- a/tools/meson.build +++ b/tools/meson.build @@ -59,24 +59,44 @@ if conf.has('WITH_HOST_VALIDATE') ] endif - executable( - 'virt-host-validate', - [ - virt_host_validate_sources, - ], - dependencies: [ - tools_dep, - ], - link_args: [ - coverage_flags, - ], - link_with: [ - libvirt_lib, - ], - install: true, - install_dir: bindir, - install_rpath: libdir, - ) + if conf.has('RPATH') + executable( + 'virt-host-validate', + [ + virt_host_validate_sources, + ], + dependencies: [ + tools_dep, + ], + link_args: [ + coverage_flags, + ], + link_with: [ + libvirt_lib, + ], + install: true, + install_dir: bindir, + install_rpath: conf.get('RPATH'), + ) + else + executable( + 'virt-host-validate', + [ + virt_host_validate_sources, + ], + dependencies: [ + tools_dep, + ], + link_args: [ + coverage_flags, + ], + link_with: [ + libvirt_lib, + ], + install: true, + install_dir: bindir, + ) + endif endif if conf.has('WITH_LOGIN_SHELL') @@ -95,25 +115,46 @@ if conf.has('WITH_LOGIN_SHELL') install_dir: bindir, ) - executable( - 'virt-login-shell-helper', - [ - 'virt-login-shell-helper.c', - ], - dependencies: [ - tools_dep, - ], - link_args: [ - coverage_flags, - ], - link_with: [ - libvirt_lib, - libvirt_lxc_lib, - ], - install: true, - install_dir: libexecdir, - install_rpath: libdir, - ) + if conf.has('RPATH') + executable( + 'virt-login-shell-helper', + [ + 'virt-login-shell-helper.c', + ], + dependencies: [ + tools_dep, + ], + link_args: [ + coverage_flags, + ], + link_with: [ + libvirt_lib, + libvirt_lxc_lib, + ], + install: true, + install_dir: libexecdir, + install_rpath: conf.get('RPATH'), + ) + else + executable( + 'virt-login-shell-helper', + [ + 'virt-login-shell-helper.c', + ], + dependencies: [ + tools_dep, + ], + link_args: [ + coverage_flags, + ], + link_with: [ + libvirt_lib, + libvirt_lxc_lib, + ], + install: true, + install_dir: libexecdir, + ) + endif install_data('virt-login-shell.conf', install_dir: sysconfdir / 'libvirt') endif @@ -149,78 +190,153 @@ else virsh_icon_res = [] endif -executable( - 'virsh', - [ - 'virsh.c', - 'virsh-backup.c', - 'virsh-checkpoint.c', - 'virsh-completer.c', - 'virsh-completer-domain.c', - 'virsh-completer-checkpoint.c', - 'virsh-completer-host.c', - 'virsh-completer-interface.c', - 'virsh-completer-network.c', - 'virsh-completer-nodedev.c', - 'virsh-completer-nwfilter.c', - 'virsh-completer-pool.c', - 'virsh-completer-secret.c', - 'virsh-completer-snapshot.c', - 'virsh-completer-volume.c', - 'virsh-console.c', - 'virsh-domain.c', - 'virsh-domain-monitor.c', - 'virsh-host.c', - 'virsh-interface.c', - 'virsh-network.c', - 'virsh-nodedev.c', - 'virsh-nwfilter.c', - 'virsh-pool.c', - 'virsh-secret.c', - 'virsh-snapshot.c', - 'virsh-util.c', - 'virsh-volume.c', - virsh_icon_res, - ], - dependencies: [ - tools_dep, - readline_dep, - thread_dep, - ], - link_args: [ - coverage_flags, - ], - link_with: [ - libvirt_lxc_lib, - libvirt_qemu_lib, - libvirt_shell_lib, - ], - install: true, - install_dir: bindir, - install_rpath: libdir, -) +if conf.has('RPATH') + executable( + 'virsh', + [ + 'virsh.c', + 'virsh-backup.c', + 'virsh-checkpoint.c', + 'virsh-completer.c', + 'virsh-completer-domain.c', + 'virsh-completer-checkpoint.c', + 'virsh-completer-host.c', + 'virsh-completer-interface.c', + 'virsh-completer-network.c', + 'virsh-completer-nodedev.c', + 'virsh-completer-nwfilter.c', + 'virsh-completer-pool.c', + 'virsh-completer-secret.c', + 'virsh-completer-snapshot.c', + 'virsh-completer-volume.c', + 'virsh-console.c', + 'virsh-domain.c', + 'virsh-domain-monitor.c', + 'virsh-host.c', + 'virsh-interface.c', + 'virsh-network.c', + 'virsh-nodedev.c', + 'virsh-nwfilter.c', + 'virsh-pool.c', + 'virsh-secret.c', + 'virsh-snapshot.c', + 'virsh-util.c', + 'virsh-volume.c', + virsh_icon_res, + ], + dependencies: [ + tools_dep, + readline_dep, + thread_dep, + ], + link_args: [ + coverage_flags, + ], + link_with: [ + libvirt_lxc_lib, + libvirt_qemu_lib, + libvirt_shell_lib, + ], + install: true, + install_dir: bindir, + install_rpath: conf.get('RPATH'), + ) +else + executable( + 'virsh', + [ + 'virsh.c', + 'virsh-backup.c', + 'virsh-checkpoint.c', + 'virsh-completer.c', + 'virsh-completer-domain.c', + 'virsh-completer-checkpoint.c', + 'virsh-completer-host.c', + 'virsh-completer-interface.c', + 'virsh-completer-network.c', + 'virsh-completer-nodedev.c', + 'virsh-completer-nwfilter.c', + 'virsh-completer-pool.c', + 'virsh-completer-secret.c', + 'virsh-completer-snapshot.c', + 'virsh-completer-volume.c', + 'virsh-console.c', + 'virsh-domain.c', + 'virsh-domain-monitor.c', + 'virsh-host.c', + 'virsh-interface.c', + 'virsh-network.c', + 'virsh-nodedev.c', + 'virsh-nwfilter.c', + 'virsh-pool.c', + 'virsh-secret.c', + 'virsh-snapshot.c', + 'virsh-util.c', + 'virsh-volume.c', + virsh_icon_res, + ], + dependencies: [ + tools_dep, + readline_dep, + thread_dep, + ], + link_args: [ + coverage_flags, + ], + link_with: [ + libvirt_lxc_lib, + libvirt_qemu_lib, + libvirt_shell_lib, + ], + install: true, + install_dir: bindir, + ) +endif -executable( - 'virt-admin', - [ - 'virt-admin.c', - 'virt-admin-completer.c', - ], - dependencies: [ - tools_dep, - readline_dep, - ], - link_args: [ - coverage_flags, - ], - link_with: [ - libvirt_admin_lib, - libvirt_shell_lib, - ], - install: true, - install_dir: bindir, - install_rpath: libdir, -) +if conf.has('RPATH') + executable( + 'virt-admin', + [ + 'virt-admin.c', + 'virt-admin-completer.c', + ], + dependencies: [ + tools_dep, + readline_dep, + ], + link_args: [ + coverage_flags, + ], + link_with: [ + libvirt_admin_lib, + libvirt_shell_lib, + ], + install: true, + install_dir: bindir, + install_rpath: conf.get('RPATH'), + ) +else + executable( + 'virt-admin', + [ + 'virt-admin.c', + 'virt-admin-completer.c', + ], + dependencies: [ + tools_dep, + readline_dep, + ], + link_args: [ + coverage_flags, + ], + link_with: [ + libvirt_admin_lib, + libvirt_shell_lib, + ], + install: true, + install_dir: bindir, + ) +endif tools_conf = configuration_data() tools_conf.set('PACKAGE', meson.project_name()) -- 2.26.2

On Wed, Aug 19, 2020 at 12:18:07PM +0200, Andrea Bolognani wrote:
Right now we're unconditionally adding RPATH information to the installed binaries and libraries, but that's not always desired
Debian explicitly passes --disable-rpath to configure, and while I haven't been able to find the same option in the spec file for either Fedora or RHEL, by running
$ readelf -d /usr/bin/virsh | grep PATH
I can see that the information is not present, so I assume they also strip it somehow.
Both Debian and Fedora have wiki pages encouraging packagers to avoid setting RPATH:
https://wiki.debian.org/RpathIssue https://fedoraproject.org/wiki/RPath_Packaging_Draft
Given the above I'm not actually sure whether there even is a valid usecase for RPATH, but I will openly admit I don't understand the problem space well enough to pass judgement. So, assuming there are scenarios where we want RPATH information to be present, our only course of action is making its inclusion configurable, just like it was with autotools.
I'd like us to query whether we really want rpath at all. I've looked at various other apps using Meson. Out of glib, networkmanager, systemd, and gtk, only systemd sets install_rpath and that's on its binaries. So I think we could likely simplify by dropping the install_rpath rules. Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

On Wed, 2020-08-19 at 11:27 +0100, Daniel P. Berrangé wrote:
On Wed, Aug 19, 2020 at 12:18:07PM +0200, Andrea Bolognani wrote:
Given the above I'm not actually sure whether there even is a valid usecase for RPATH, but I will openly admit I don't understand the problem space well enough to pass judgement. So, assuming there are scenarios where we want RPATH information to be present, our only course of action is making its inclusion configurable, just like it was with autotools.
I'd like us to query whether we really want rpath at all.
I've looked at various other apps using Meson. Out of glib, networkmanager, systemd, and gtk, only systemd sets install_rpath and that's on its binaries.
So I think we could likely simplify by dropping the install_rpath rules.
That was my thought as well, but I figured I would act conservatively and try to preserve the current behavior. I'll post an alternative patch getting rid of RPATH altogether. -- Andrea Bolognani / Red Hat / Virtualization

Neither Fedora nor RHEL seem to include RPATH information in the binaries and libraries they currently ship, so let's make sure RPMs built from upstream sources match that behavior. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- libvirt.spec.in | 1 + 1 file changed, 1 insertion(+) diff --git a/libvirt.spec.in b/libvirt.spec.in index e64cfdb561..2a5b930de1 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -1132,6 +1132,7 @@ exit 1 export SOURCE_DATE_EPOCH=$(stat --printf='%Y' %{_specdir}/%{name}.spec) %meson \ + -Drpath=false \ -Drunstatedir=%{_rundir} \ %{?arg_qemu} \ %{?arg_openvz} \ -- 2.26.2
participants (2)
-
Andrea Bolognani
-
Daniel P. Berrangé