Build a top-level qemu-system executable when multiple supported targets
are configured.

Now the test-multi-target.c are testing under no target selected condition.
That's guard for future breakage

Signed-off-by: Yonggang Luo <[email protected]>
---
 MAINTAINERS                    |  1 +
 meson.build                    | 58 ++++++++++++++++++++++++++++++++++
 qom/object.c                   |  4 ++-
 system/target-info.c           | 10 ++++++
 tests/unit/meson.build         |  4 +--
 tests/unit/test-multi-target.c |  5 ++-
 6 files changed, 76 insertions(+), 6 deletions(-)
 create mode 100644 system/target-info.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 669814d29c5..51012672b0f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2147,6 +2147,7 @@ M: Pierrick Bouvier <[email protected]>
 M: Philippe Mathieu-Daudé <[email protected]>
 S: Supported
 F: stubs/target-info.c
+F: system/target-info.c
 F: include/qemu/target-info*.h
 F: target-info*.c
 F: tests/unit/test-multi-targets.c
diff --git a/meson.build b/meson.build
index f54687e19dc..6e90760c05a 100644
--- a/meson.build
+++ b/meson.build
@@ -4275,6 +4275,7 @@ multi_target_supported_targets = [
   'rx-softmmu',
   'tricore-softmmu',
 ]
+multi_target_final_targets = []
 
 emulators = {}
 foreach target : target_dirs
@@ -4436,6 +4437,7 @@ foreach target : target_dirs
           multi_target_crates += crate
         endif
       endforeach
+      multi_target_final_targets += target
     endif
     execs = [{
       'name': 'qemu-system-' + target_name,
@@ -4540,6 +4542,62 @@ endforeach
 multi_target_link_args = emulator_link_args
 multi_target_link_args += enable_modules ? ['@block.syms', '@qemu.syms'] : []
 
+if multi_target_final_targets.length() > 1
+  qemu_system_name = 'qemu-system'
+  if host_os == 'darwin'
+    qemu_system_name += '-unsigned'
+  endif
+  multi_target_info_sources = files('system/target-info.c')
+  qemu_system_sources = [
+    multi_target_crates,
+    files('system/main.c'),
+    multi_target_info_sources,
+  ]
+  qemu_system = executable(qemu_system_name,
+                           sources: qemu_system_sources,
+                           dependencies: multi_target_deps + [sdl],
+                           objects: multi_target_objects,
+                           link_depends: [block_syms, qemu_syms],
+                           link_args: multi_target_link_args,
+                           build_by_default: true,
+                           install: true)
+  multi_target_info_objects = qemu_system.extract_objects(
+    multi_target_info_sources)
+  if host_os == 'darwin'
+    icon = 'pc-bios/qemu.rsrc'
+    build_input = [qemu_system, files(icon)]
+    install_input = [
+      get_option('bindir') / qemu_system_name,
+      meson.current_source_dir() / icon
+    ]
+    if 'CONFIG_HVF' in multi_target_config
+      entitlements = 'accel/hvf/entitlements.plist'
+      build_input += files(entitlements)
+      install_input += meson.current_source_dir() / entitlements
+    endif
+    emulators += {'qemu-system': custom_target('qemu-system',
+                 input: build_input,
+                 output: 'qemu-system',
+                 build_by_default: true,
+                 command: [entitlement, '@OUTPUT@', '@INPUT@'])
+    }
+    meson.add_install_script(entitlement, '--install',
+                             get_option('bindir') / 'qemu-system',
+                             install_input)
+  else
+    emulators += {'qemu-system': qemu_system}
+  endif
+else
+  error_str = f'''qemu-system only support targets:
+@multi_target_supported_targets@
+
+use ./configure --target-list= to choose at least one of them'''
+  t = custom_target(command: ['sh', '-c', 'echo "' + error_str + '" && exit 
1'],
+                    output: 'none',
+                    build_by_default: false)
+  alias_target('qemu-system', t)
+endif
+
 if get_option('plugins')
   install_headers('include/plugins/qemu-plugin.h')
   if host_os == 'windows'
diff --git a/qom/object.c b/qom/object.c
index 96498f3d001..f05456bd701 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -12,6 +12,7 @@
 
 #include "qemu/osdep.h"
 #include "qapi/error.h"
+#include "qemu/target-info.h"
 #include "qom/compat-properties.h"
 #include "qom/object.h"
 #include "qom/object_interfaces.h"
@@ -167,7 +168,8 @@ static TypeImpl *type_register_internal(const TypeInfo 
*info)
         abort();
     }
 
-    if (info->is_available && !info->is_available()) {
+    if (!target_combined_binary()
+        && info->is_available && !info->is_available()) {
         return NULL;
     }
 
diff --git a/system/target-info.c b/system/target-info.c
new file mode 100644
index 00000000000..fb13ea8ad22
--- /dev/null
+++ b/system/target-info.c
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "qemu/osdep.h"
+
+#include "qemu/target-info.h"
+
+bool target_combined_binary(void)
+{
+    return true;
+}
diff --git a/tests/unit/meson.build b/tests/unit/meson.build
index d17435c1877..4bc7c4c146f 100644
--- a/tests/unit/meson.build
+++ b/tests/unit/meson.build
@@ -217,12 +217,12 @@ foreach test_name, extra: tests
 endforeach
 
 # Multi targets test
-if multi_target_objects != []
+if is_variable('qemu_system')
   test('test-multi-target',
        executable('test-multi-target',
                   sources: [multi_target_crates, files('test-multi-target.c')],
                   dependencies: multi_target_deps,
-                  objects: multi_target_objects,
+                  objects: multi_target_objects + multi_target_info_objects,
                   link_depends: [block_syms, qemu_syms],
                   link_args: multi_target_link_args),
        suite: ['unit'])
diff --git a/tests/unit/test-multi-target.c b/tests/unit/test-multi-target.c
index 704e3297ef9..ff81ea42a90 100644
--- a/tests/unit/test-multi-target.c
+++ b/tests/unit/test-multi-target.c
@@ -49,6 +49,8 @@ static bool target_arch_available(uint64_t arch_mask)
 static void test_qom_types_are_unique(void)
 {
     g_assert(targets);
+    /* Verify this test runs like the combined qemu-system binary. */
+    g_assert_true(target_combined_binary());
     /* trigger type_initialize for all types */
     object_class_get_list("", false);
 
@@ -89,9 +91,6 @@ int main(int argc, char **argv)
     target_info_qom_init();
     targets = target_info_qom_get_targets();
 
-    const TargetInfo *first_ti = TARGET_INFO_CLASS(targets->data)->target_info;
-    target_info_qom_set_target_info(first_ti);
-
     /* register all types */
     module_call_init(MODULE_INIT_QOM);
 
-- 
2.55.0.windows.3


Reply via email to