From: Akihiko Odaki <akihiko.odaki@gmail.com>
Cc: "Peter Maydell" <peter.maydell@linaro.org>,
"Jason Wang" <jasowang@redhat.com>,
qemu-devel@nongnu.org, Programmingkid <programmingkidx@gmail.com>,
"Philippe Mathieu-Daudé" <f4bug@amsat.org>,
"Gerd Hoffmann" <kraxel@redhat.com>,
"Daniel P . Berrangé" <berrange@redhat.com>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Alex Bennée" <alex.bennee@linaro.org>,
"Thomas Huth" <thuth@redhat.com>, "John Snow" <jsnow@redhat.com>,
"Cleber Rosa" <crosa@redhat.com>, "Stefan Weil" <sw@weilnetz.de>,
"Akihiko Odaki" <akihiko.odaki@gmail.com>
Subject: [PATCH v10 2/4] cutils: Introduce bundle mechanism
Date: Mon, 27 Jun 2022 12:57:42 +0900 [thread overview]
Message-ID: <20220627035744.23218-3-akihiko.odaki@gmail.com> (raw)
In-Reply-To: <20220627035744.23218-1-akihiko.odaki@gmail.com>
Developers often run QEMU without installing. The bundle mechanism
allows to look up files which should be present in installation even in
such a situation.
It is a general mechanism and can find any files in the installation
tree. The build tree will have a new directory, qemu-bundle, to
represent what files the installation tree would have for reference by
the executables.
Note that it abandons compatibility with Windows older than 8. The
extended support for the prior version, 7 ended more than 2 years ago,
and it is unlikely that someone would like to run the latest QEMU on
such an old system.
Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com>
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
---
docs/about/build-platforms.rst | 2 +-
include/qemu/cutils.h | 18 +++++++--
include/qemu/osdep.h | 2 +-
meson.build | 4 ++
scripts/symlink-install-tree.py | 34 +++++++++++++++++
util/cutils.c | 68 +++++++++++++++++++++++----------
util/meson.build | 1 +
7 files changed, 103 insertions(+), 26 deletions(-)
create mode 100755 scripts/symlink-install-tree.py
diff --git a/docs/about/build-platforms.rst b/docs/about/build-platforms.rst
index 1958edb4305..ebde20f9815 100644
--- a/docs/about/build-platforms.rst
+++ b/docs/about/build-platforms.rst
@@ -88,7 +88,7 @@ Windows
The project aims to support the two most recent versions of Windows that are
still supported by the vendor. The minimum Windows API that is currently
-targeted is "Windows 7", so theoretically the QEMU binaries can still be run
+targeted is "Windows 8", so theoretically the QEMU binaries can still be run
on older versions of Windows, too. However, such old versions of Windows are
not tested anymore, so it is recommended to use one of the latest versions of
Windows instead.
diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h
index d3e532b64c8..92c436d8c70 100644
--- a/include/qemu/cutils.h
+++ b/include/qemu/cutils.h
@@ -224,9 +224,21 @@ const char *qemu_get_exec_dir(void);
* @dir: the directory (typically a `CONFIG_*DIR` variable) to be relocated.
*
* Returns a path for @dir that uses the directory of the running executable
- * as the prefix. For example, if `bindir` is `/usr/bin` and @dir is
- * `/usr/share/qemu`, the function will append `../share/qemu` to the
- * directory that contains the running executable and return the result.
+ * as the prefix.
+ *
+ * When a directory named `qemu-bundle` exists in the directory of the running
+ * executable, the path to the directory will be prepended to @dir. For
+ * example, if the directory of the running executable is `/qemu/build` @dir
+ * is `/usr/share/qemu`, the result will be
+ * `/qemu/build/qemu-bundle/usr/share/qemu`. The directory is expected to exist
+ * in the build tree.
+ *
+ * Otherwise, the directory of the running executable will be used as the
+ * prefix and it appends the relative path from `bindir` to @dir. For example,
+ * if the directory of the running executable is `/opt/qemu/bin`, `bindir` is
+ * `/usr/bin` and @dir is `/usr/share/qemu`, the result will be
+ * `/opt/qemu/bin/../share/qemu`.
+ *
* The returned string should be freed by the caller.
*/
char *get_relocated_path(const char *dir);
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index b1c161c035a..84f8b9d0243 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -75,7 +75,7 @@ QEMU_EXTERN_C int daemon(int, int);
#ifdef _WIN32
/* as defined in sdkddkver.h */
#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x0601 /* Windows 7 API (should be in sync with glib) */
+#define _WIN32_WINNT 0x0602 /* Windows 8 API (should be in sync with glib) */
#endif
/* reduces the number of implicitly included headers */
#ifndef WIN32_LEAN_AND_MEAN
diff --git a/meson.build b/meson.build
index 9efcb175d16..c49f5ebfc37 100644
--- a/meson.build
+++ b/meson.build
@@ -7,6 +7,8 @@ add_test_setup('quick', exclude_suites: ['slow', 'thorough'], is_default: true)
add_test_setup('slow', exclude_suites: ['thorough'], env: ['G_TEST_SLOW=1', 'SPEED=slow'])
add_test_setup('thorough', env: ['G_TEST_SLOW=1', 'SPEED=thorough'])
+meson.add_postconf_script('scripts/symlink-install-tree.py')
+
not_found = dependency('', required: false)
keyval = import('keyval')
ss = import('sourceset')
@@ -356,10 +358,12 @@ nvmm =not_found
hvf = not_found
midl = not_found
widl = not_found
+pathcch = not_found
host_dsosuf = '.so'
if targetos == 'windows'
midl = find_program('midl', required: false)
widl = find_program('widl', required: false)
+ pathcch = cc.find_library('pathcch')
socket = cc.find_library('ws2_32')
winmm = cc.find_library('winmm')
diff --git a/scripts/symlink-install-tree.py b/scripts/symlink-install-tree.py
new file mode 100755
index 00000000000..59cf7e939f1
--- /dev/null
+++ b/scripts/symlink-install-tree.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python3
+
+from pathlib import PurePath
+import errno
+import json
+import os
+import subprocess
+import sys
+
+def destdir_join(d1: str, d2: str) -> str:
+ if not d1:
+ return d2
+ # c:\destdir + c:\prefix must produce c:\destdir\prefix
+ return str(PurePath(d1, *PurePath(d2).parts[1:]))
+
+introspect = os.environ.get('MESONINTROSPECT')
+out = subprocess.run([*introspect.split(' '), '--installed'],
+ stdout=subprocess.PIPE, check=True).stdout
+for source, dest in json.loads(out).items():
+ assert os.path.isabs(source)
+ assert os.path.isabs(dest)
+ bundle_dest = destdir_join('qemu-bundle', dest)
+ path = os.path.dirname(bundle_dest)
+ try:
+ os.makedirs(path, exist_ok=True)
+ except BaseException as e:
+ print(f'error making directory {path}', file=sys.stderr)
+ raise e
+ try:
+ os.symlink(source, bundle_dest)
+ except BaseException as e:
+ if not isinstance(e, OSError) or e.errno != errno.EEXIST:
+ print(f'error making symbolic link {dest}', file=sys.stderr)
+ raise e
diff --git a/util/cutils.c b/util/cutils.c
index 6d04e52907b..8199dac5988 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -35,6 +35,11 @@
#include <sys/sysctl.h>
#endif
+#ifdef G_OS_WIN32
+#include <pathcch.h>
+#include <wchar.h>
+#endif
+
#include "qemu/ctype.h"
#include "qemu/cutils.h"
#include "qemu/error-report.h"
@@ -1074,31 +1079,52 @@ char *get_relocated_path(const char *dir)
/* Fail if qemu_init_exec_dir was not called. */
assert(exec_dir[0]);
- if (!starts_with_prefix(dir) || !starts_with_prefix(bindir)) {
- return g_strdup(dir);
- }
result = g_string_new(exec_dir);
+ g_string_append(result, "/qemu-bundle");
+ if (access(result->str, R_OK) == 0) {
+#ifdef G_OS_WIN32
+ size_t size = mbsrtowcs(NULL, &dir, 0, &(mbstate_t){0}) + 1;
+ PWSTR wdir = g_new(WCHAR, size);
+ mbsrtowcs(wdir, &dir, size, &(mbstate_t){0});
+
+ PCWSTR wdir_skipped_root;
+ PathCchSkipRoot(wdir, &wdir_skipped_root);
+
+ size = wcsrtombs(NULL, &wdir_skipped_root, 0, &(mbstate_t){0});
+ char *cursor = result->str + result->len;
+ g_string_set_size(result, result->len + size);
+ wcsrtombs(cursor, &wdir_skipped_root, size + 1, &(mbstate_t){0});
+ g_free(wdir);
+#else
+ g_string_append(result, dir);
+#endif
+ } else if (!starts_with_prefix(dir) || !starts_with_prefix(bindir)) {
+ g_string_assign(result, dir);
+ } else {
+ g_string_assign(result, exec_dir);
+
+ /* Advance over common components. */
+ len_dir = len_bindir = prefix_len;
+ do {
+ dir += len_dir;
+ bindir += len_bindir;
+ dir = next_component(dir, &len_dir);
+ bindir = next_component(bindir, &len_bindir);
+ } while (len_dir && len_dir == len_bindir && !memcmp(dir, bindir, len_dir));
+
+ /* Ascend from bindir to the common prefix with dir. */
+ while (len_bindir) {
+ bindir += len_bindir;
+ g_string_append(result, "/..");
+ bindir = next_component(bindir, &len_bindir);
+ }
- /* Advance over common components. */
- len_dir = len_bindir = prefix_len;
- do {
- dir += len_dir;
- bindir += len_bindir;
- dir = next_component(dir, &len_dir);
- bindir = next_component(bindir, &len_bindir);
- } while (len_dir && len_dir == len_bindir && !memcmp(dir, bindir, len_dir));
-
- /* Ascend from bindir to the common prefix with dir. */
- while (len_bindir) {
- bindir += len_bindir;
- g_string_append(result, "/..");
- bindir = next_component(bindir, &len_bindir);
+ if (*dir) {
+ assert(G_IS_DIR_SEPARATOR(dir[-1]));
+ g_string_append(result, dir - 1);
+ }
}
- if (*dir) {
- assert(G_IS_DIR_SEPARATOR(dir[-1]));
- g_string_append(result, dir - 1);
- }
return g_string_free(result, false);
}
diff --git a/util/meson.build b/util/meson.build
index 8f16018cd43..6cacb8689f1 100644
--- a/util/meson.build
+++ b/util/meson.build
@@ -23,6 +23,7 @@ util_ss.add(when: 'CONFIG_WIN32', if_true: files('event_notifier-win32.c'))
util_ss.add(when: 'CONFIG_WIN32', if_true: files('oslib-win32.c'))
util_ss.add(when: 'CONFIG_WIN32', if_true: files('qemu-thread-win32.c'))
util_ss.add(when: 'CONFIG_WIN32', if_true: winmm)
+util_ss.add(when: 'CONFIG_WIN32', if_true: pathcch)
util_ss.add(files('envlist.c', 'path.c', 'module.c'))
util_ss.add(files('host-utils.c'))
util_ss.add(files('bitmap.c', 'bitops.c'))
--
2.32.1 (Apple Git-133)
next prev parent reply other threads:[~2022-06-27 4:18 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-06-27 3:57 [PATCH v10 0/4] cutils: Introduce bundle mechanism Akihiko Odaki
2022-06-27 3:57 ` [PATCH v10 1/4] tests/vm: do not specify -bios option Akihiko Odaki
2022-06-27 3:57 ` Akihiko Odaki [this message]
2022-06-27 3:57 ` [PATCH v10 3/4] datadir: Use bundle mechanism Akihiko Odaki
2022-06-27 3:57 ` [PATCH v10 4/4] module: " Akihiko Odaki
2022-07-11 15:42 ` [PATCH v10 0/4] cutils: Introduce " Paolo Bonzini
2022-10-29 8:51 ` Stefan Weil via
2022-10-29 19:45 ` Paolo Bonzini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220627035744.23218-3-akihiko.odaki@gmail.com \
--to=akihiko.odaki@gmail.com \
--cc=alex.bennee@linaro.org \
--cc=berrange@redhat.com \
--cc=crosa@redhat.com \
--cc=f4bug@amsat.org \
--cc=jasowang@redhat.com \
--cc=jsnow@redhat.com \
--cc=kraxel@redhat.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=programmingkidx@gmail.com \
--cc=qemu-devel@nongnu.org \
--cc=sw@weilnetz.de \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).