Now we are able to link multiple targets together, we want to make sure
no build regression is introduced. For this, add a new unit test linking
compatible targets.

In addition, we check QOM types can be initialized, ensuring uniqueness
among all targets.

For now, supported targets are:
- arm-softmmu
- aarch64-softmmu
- microblaze-softmmu

Signed-off-by: Pierrick Bouvier <[email protected]>
---
 MAINTAINERS                    |  1 +
 include/qemu/target-info-qom.h |  1 +
 meson.build                    | 23 +++++++++++++++
 target-info-qom.c              |  5 ++++
 tests/unit/meson.build         | 12 ++++++++
 tests/unit/test-multi-target.c | 53 ++++++++++++++++++++++++++++++++++
 6 files changed, 95 insertions(+)
 create mode 100644 tests/unit/test-multi-target.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 6be9c5725b9..62e048d1824 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2146,6 +2146,7 @@ S: Supported
 F: include/qemu/target-info*.h
 F: target-info*.c
 F: configs/targets/*.c
+F: tests/unit/test-multi-targets.c
 
 Xtensa Machines
 ---------------
diff --git a/include/qemu/target-info-qom.h b/include/qemu/target-info-qom.h
index 91be415ed33..8b6e1ece969 100644
--- a/include/qemu/target-info-qom.h
+++ b/include/qemu/target-info-qom.h
@@ -26,5 +26,6 @@ typedef struct TargetInfoQomClass {
 OBJECT_DECLARE_TYPE(TargetInfoQom, TargetInfoQomClass, TARGET_INFO)
 
 void target_info_qom_set_target(void);
+void target_info_qom_set_target_info(const TargetInfo *ti);
 
 #endif /* QEMU_TARGET_INFO_QOM_H */
diff --git a/meson.build b/meson.build
index cfac634cf13..cae1591cd28 100644
--- a/meson.build
+++ b/meson.build
@@ -4259,6 +4259,15 @@ if host_os == 'darwin'
 endif
 
 traceable = []
+multi_target_libs = []
+multi_target_deps = []
+multi_target_crates = []
+multi_target_supported_targets = [
+  'aarch64-softmmu',
+  'arm-softmmu',
+  'microblaze-softmmu',
+]
+
 emulators = {}
 foreach target : target_dirs
   config_target = config_target_mak[target]
@@ -4414,6 +4423,12 @@ foreach target : target_dirs
                  build_by_default: false)
 
   if target.endswith('-softmmu')
+    if target in multi_target_supported_targets
+      multi_target_libs += lib
+      multi_target_deps += arch_deps
+      multi_target_deps += target_stubs
+      multi_target_crates += main_rs
+    endif
     execs = [{
       'name': 'qemu-system-' + target_name,
       'win_subsystem': 'console',
@@ -4497,6 +4512,14 @@ endforeach
 
 # Other build targets
 
+multi_target_objects = []
+foreach lib: multi_target_libs
+  multi_target_objects += lib.extract_all_objects(recursive: true)
+endforeach
+
+multi_target_link_args = emulator_link_args
+multi_target_link_args += enable_modules ? ['@block.syms', '@qemu.syms'] : []
+
 if get_option('plugins')
   install_headers('include/plugins/qemu-plugin.h')
   if host_os == 'windows'
diff --git a/target-info-qom.c b/target-info-qom.c
index 6965e4d1169..3ae1627b8fb 100644
--- a/target-info-qom.c
+++ b/target-info-qom.c
@@ -53,3 +53,8 @@ void target_info_qom_set_target(void)
 
     target_info_ptr = TARGET_INFO_CLASS(targets->data)->target_info;
 }
+
+void target_info_qom_set_target_info(const TargetInfo *ti)
+{
+    target_info_ptr = ti;
+}
diff --git a/tests/unit/meson.build b/tests/unit/meson.build
index e47bc7225ab..d17435c1877 100644
--- a/tests/unit/meson.build
+++ b/tests/unit/meson.build
@@ -215,3 +215,15 @@ foreach test_name, extra: tests
        suite: ['unit'] +
               (slow_tests.has_key(test_name) ? ['slow'] : []))
 endforeach
+
+# Multi targets test
+if multi_target_objects != []
+  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,
+                  link_depends: [block_syms, qemu_syms],
+                  link_args: multi_target_link_args),
+       suite: ['unit'])
+endif
diff --git a/tests/unit/test-multi-target.c b/tests/unit/test-multi-target.c
new file mode 100644
index 00000000000..89b55bb1632
--- /dev/null
+++ b/tests/unit/test-multi-target.c
@@ -0,0 +1,53 @@
+/*
+ * Test for multiple targets
+ *
+ * Ensures targets compatible can be linked together.
+ * Also that each QOM type is unique among them and can be initialized.
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * Author:
+ *  Pierrick Bouvier <[email protected]>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/module.h"
+#include "qemu/target-info.h"
+#include "qemu/target-info-qom.h"
+#include "qom/object.h"
+
+#ifdef CONFIG_SDL
+/*
+ * SDL insists on wrapping the main() function with its own implementation on
+ * some platforms; it does so via a macro that renames our main function, so
+ * <SDL.h> must be #included here even with no SDL code called from this file.
+ */
+#include <SDL.h>
+#endif
+
+/* stub for system/main.c */
+int (*qemu_main)(void);
+
+static void test_qom_types_are_unique(void)
+{
+    module_call_init(MODULE_INIT_TARGET_INFO);
+    g_autoptr(GSList) targets = object_class_get_list(TYPE_TARGET_INFO, false);
+    g_assert(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);
+    /* trigger type_initialize for all types */
+    object_class_get_list("", false);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+    g_test_add_func("/multi-targets/qom-types-are-unique",
+                   test_qom_types_are_unique);
+    return g_test_run();
+}
-- 
2.43.0


Reply via email to