diff mbox series

[03/17] meson, cutils: allow non-relocatable installs

Message ID 20231016063127.161204-4-pbonzini@redhat.com
State New
Headers show
Series More build system cleanups, optional non-relocatable installs | expand

Commit Message

Paolo Bonzini Oct. 16, 2023, 6:31 a.m. UTC
Suggested-by: Michael Tokarev <mjt@tls.msk.ru>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 meson.build                   | 21 +++++++++++++++++++++
 meson_options.txt             |  2 ++
 scripts/meson-buildoptions.sh |  3 +++
 util/cutils.c                 | 11 ++++++++---
 4 files changed, 34 insertions(+), 3 deletions(-)

Comments

Markus Armbruster Oct. 16, 2023, 7:12 a.m. UTC | #1
Out of curiosity: what's a non-relocatable install, and why should I
care?
Manos Pitsidianakis Oct. 16, 2023, 9:08 a.m. UTC | #2
On Mon, 16 Oct 2023 09:31, Paolo Bonzini <pbonzini@redhat.com> wrote:
>diff --git a/meson.build b/meson.build
>index 010d2c649c2..251838f2609 100644
>--- a/meson.build
>+++ b/meson.build
>@@ -2111,6 +2111,7 @@ config_host_data.set('CONFIG_OPENGL', opengl.found())
> config_host_data.set('CONFIG_PLUGIN', get_option('plugins'))
> config_host_data.set('CONFIG_RBD', rbd.found())
> config_host_data.set('CONFIG_RDMA', rdma.found())
>+config_host_data.set('CONFIG_RELOCATABLE', get_option('relocatable'))
> config_host_data.set('CONFIG_SAFESTACK', get_option('safe_stack'))
> config_host_data.set('CONFIG_SDL', sdl.found())
> config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())

Is relocatable a good choice here? The term is used in linking and might 
be confusing (when I read the subject that's what I thought it'd be 
about). How about 'movable`?

Otherwise:

Reviewed-by: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
Paolo Bonzini Oct. 16, 2023, 9:48 a.m. UTC | #3
On 10/16/23 11:08, Manos Pitsidianakis wrote:
> On Mon, 16 Oct 2023 09:31, Paolo Bonzini <pbonzini@redhat.com> wrote:
>> diff --git a/meson.build b/meson.build
>> index 010d2c649c2..251838f2609 100644
>> --- a/meson.build
>> +++ b/meson.build
>> @@ -2111,6 +2111,7 @@ config_host_data.set('CONFIG_OPENGL', 
>> opengl.found())
>> config_host_data.set('CONFIG_PLUGIN', get_option('plugins'))
>> config_host_data.set('CONFIG_RBD', rbd.found())
>> config_host_data.set('CONFIG_RDMA', rdma.found())
>> +config_host_data.set('CONFIG_RELOCATABLE', get_option('relocatable'))
>> config_host_data.set('CONFIG_SAFESTACK', get_option('safe_stack'))
>> config_host_data.set('CONFIG_SDL', sdl.found())
>> config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
> 
> Is relocatable a good choice here? The term is used in linking and might 
> be confusing (when I read the subject that's what I thought it'd be 
> about). How about 'movable`?

I think it's a relatively common usage.  Google finds many uses for RPM 
but also in a lot of random forums (CMake, Julia, FreeBSD).  See also 
https://nehckl0.medium.com/creating-relocatable-linux-executables-by-setting-rpath-with-origin-45de573a2e98 
or 
https://www.gnu.org/software/gnulib/manual/html_node/Supporting-Relocation.html.

Paolo
Paolo Bonzini Oct. 16, 2023, 9:29 p.m. UTC | #4
On Mon, Oct 16, 2023 at 1:55 PM Markus Armbruster <armbru@redhat.com> wrote:
> Out of curiosity: what's a non-relocatable install, and why should I
> care?

In a relocatable install if you move qemu-system-x86_64 from /usr/bin
to /home/armbru/bin, it will start looking for firmware in
/home/armbru/share/qemu.

In a non-relocatable install, it will keep looking for firmware in
/usr/share/qemu.

Whether that's something desirable or not... it depends.

On POSIX systems you almost never notice. Non-relocatability can help
if you want to do experiments with old firmware and new QEMU or vice
versa (because you can just upgrade/downgrade the firmware package,
and use rpm2cpio to extract the QEMU binaries outside /usr).

On the other hand Windows almost always wants relocatable installs,
which is why the whole idea was introduced in QEMU in fact. Newfangled
distribution mechanisms such as AppImage
(https://docs.appimage.org/reference/best-practices.html) and I think
NixOS (which installs each package in its own prefix, so you can
install multiple versions and switch at will the one that is symlinked
to /usr) also dislike using at runtime the absolute paths that were
established at build time.

Finally, the same code that handles relocation also lets you run QEMU
from the build tree and pick e.g. firmware files from the source tree
transparently. Even with this patch, that part of the code remains
active even if you configure with --disable-relocatable.

IOW: you probably have relied on the code, but if you have never
noticed in the past 3 years, it means that you probably need not care.

Paolo
Markus Armbruster Oct. 17, 2023, 5:46 a.m. UTC | #5
Paolo Bonzini <pbonzini@redhat.com> writes:

> On Mon, Oct 16, 2023 at 1:55 PM Markus Armbruster <armbru@redhat.com> wrote:
>> Out of curiosity: what's a non-relocatable install, and why should I
>> care?
>
> In a relocatable install if you move qemu-system-x86_64 from /usr/bin
> to /home/armbru/bin, it will start looking for firmware in
> /home/armbru/share/qemu.
>
> In a non-relocatable install, it will keep looking for firmware in
> /usr/share/qemu.
>
> Whether that's something desirable or not... it depends.
>
> On POSIX systems you almost never notice. Non-relocatability can help
> if you want to do experiments with old firmware and new QEMU or vice
> versa (because you can just upgrade/downgrade the firmware package,
> and use rpm2cpio to extract the QEMU binaries outside /usr).
>
> On the other hand Windows almost always wants relocatable installs,
> which is why the whole idea was introduced in QEMU in fact. Newfangled
> distribution mechanisms such as AppImage
> (https://docs.appimage.org/reference/best-practices.html) and I think
> NixOS (which installs each package in its own prefix, so you can
> install multiple versions and switch at will the one that is symlinked
> to /usr) also dislike using at runtime the absolute paths that were
> established at build time.
>
> Finally, the same code that handles relocation also lets you run QEMU
> from the build tree and pick e.g. firmware files from the source tree
> transparently. Even with this patch, that part of the code remains
> active even if you configure with --disable-relocatable.
>
> IOW: you probably have relied on the code, but if you have never
> noticed in the past 3 years, it means that you probably need not care.

I think this would make a fine commit message body :)

Thanks!
diff mbox series

Patch

diff --git a/meson.build b/meson.build
index 010d2c649c2..251838f2609 100644
--- a/meson.build
+++ b/meson.build
@@ -2111,6 +2111,7 @@  config_host_data.set('CONFIG_OPENGL', opengl.found())
 config_host_data.set('CONFIG_PLUGIN', get_option('plugins'))
 config_host_data.set('CONFIG_RBD', rbd.found())
 config_host_data.set('CONFIG_RDMA', rdma.found())
+config_host_data.set('CONFIG_RELOCATABLE', get_option('relocatable'))
 config_host_data.set('CONFIG_SAFESTACK', get_option('safe_stack'))
 config_host_data.set('CONFIG_SDL', sdl.found())
 config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
@@ -4054,6 +4055,7 @@  if 'simple' in get_option('trace_backends')
 endif
 summary_info += {'D-Bus display':     dbus_display}
 summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
+summary_info += {'Relocatable install': get_option('relocatable')}
 summary_info += {'vhost-kernel support': have_vhost_kernel}
 summary_info += {'vhost-net support': have_vhost_net}
 summary_info += {'vhost-user support': have_vhost_user}
@@ -4356,3 +4358,22 @@  if host_arch == 'unknown' or not supported_oses.contains(targetos)
   message('If you want to help supporting QEMU on this platform, please')
   message('contact the developers at qemu-devel@nongnu.org.')
 endif
+
+actually_reloc = get_option('relocatable')
+# check if get_relocated_path() is actually able to relocate paths
+if get_option('relocatable') and \
+  not (get_option('prefix') / get_option('bindir')).startswith(get_option('prefix') / '')
+  message()
+  warning('bindir not included within prefix, the installation will not be relocatable.')
+  message()
+  message('Use --disable-relocatable to remove this warning.')
+  actually_reloc = false
+endif
+if not actually_reloc and (targetos == 'windows' or get_option('relocatable'))
+  if targetos == 'windows'
+    message()
+    warning('Windows installs should usually be relocatable.')
+  endif
+  message()
+  message('QEMU will have to be installed under ' + get_option('prefix') + '.')
+endif
diff --git a/meson_options.txt b/meson_options.txt
index 6a17b909680..e237b268469 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -101,6 +101,8 @@  option('cfi_debug', type: 'boolean', value: false,
        description: 'Verbose errors in case of CFI violation')
 option('multiprocess', type: 'feature', value: 'auto',
        description: 'Out of process device emulation support')
+option('relocatable', type : 'boolean', value : 'true',
+       description: 'toggle relocatable install')
 option('vfio_user_server', type: 'feature', value: 'disabled',
        description: 'vfio-user server support')
 option('dbus_display', type: 'feature', value: 'auto',
diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh
index 2a74b0275b3..d4b89e6b443 100644
--- a/scripts/meson-buildoptions.sh
+++ b/scripts/meson-buildoptions.sh
@@ -17,6 +17,7 @@  meson_options_help() {
   printf "%s\n" '                           code for the Hexagon frontend'
   printf "%s\n" '  --disable-install-blobs  install provided firmware blobs'
   printf "%s\n" '  --disable-qom-cast-debug cast debugging support'
+  printf "%s\n" '  --disable-relocatable    toggle relocatable install'
   printf "%s\n" '  --docdir=VALUE           Base directory for documentation installation'
   printf "%s\n" '                           (can be empty) [share/doc]'
   printf "%s\n" '  --enable-block-drv-whitelist-in-tools'
@@ -421,6 +422,8 @@  _meson_option_parse() {
     --disable-rbd) printf "%s" -Drbd=disabled ;;
     --enable-rdma) printf "%s" -Drdma=enabled ;;
     --disable-rdma) printf "%s" -Drdma=disabled ;;
+    --enable-relocatable) printf "%s" -Drelocatable=true ;;
+    --disable-relocatable) printf "%s" -Drelocatable=false ;;
     --enable-replication) printf "%s" -Dreplication=enabled ;;
     --disable-replication) printf "%s" -Dreplication=disabled ;;
     --enable-rng-none) printf "%s" -Drng_none=true ;;
diff --git a/util/cutils.c b/util/cutils.c
index c99d26c5e2d..64f817b477b 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -1178,9 +1178,11 @@  char *get_relocated_path(const char *dir)
 #else
         g_string_append(result, dir);
 #endif
-    } else if (!starts_with_prefix(dir) || !starts_with_prefix(bindir)) {
-        g_string_assign(result, dir);
-    } else {
+        goto out;
+    }
+
+    if (IS_ENABLED(CONFIG_RELOCATABLE) &&
+        starts_with_prefix(dir) && starts_with_prefix(bindir)) {
         g_string_assign(result, exec_dir);
 
         /* Advance over common components.  */
@@ -1203,7 +1205,10 @@  char *get_relocated_path(const char *dir)
             assert(G_IS_DIR_SEPARATOR(dir[-1]));
             g_string_append(result, dir - 1);
         }
+        goto out;
     }
 
+    g_string_assign(result, dir);
+out:
     return g_string_free(result, false);
 }