xref: /openbmc/qemu/meson.build (revision b56d351e25065d46fb959081fe13e8d031df35f3)
1project('qemu', ['c'], meson_version: '>=0.55.0',
2        default_options: ['warning_level=1', 'c_std=gnu99', 'cpp_std=gnu++11', 'b_colorout=auto'] +
3                         (meson.version().version_compare('>=0.56.0') ? [ 'b_staticpic=false' ] : []),
4        version: run_command('head', meson.source_root() / 'VERSION').stdout().strip())
5
6not_found = dependency('', required: false)
7if meson.version().version_compare('>=0.56.0')
8  keyval = import('keyval')
9else
10  keyval = import('unstable-keyval')
11endif
12ss = import('sourceset')
13fs = import('fs')
14
15sh = find_program('sh')
16cc = meson.get_compiler('c')
17config_host = keyval.load(meson.current_build_dir() / 'config-host.mak')
18enable_modules = 'CONFIG_MODULES' in config_host
19enable_static = 'CONFIG_STATIC' in config_host
20
21# Temporary directory used for files created while
22# configure runs. Since it is in the build directory
23# we can safely blow away any previous version of it
24# (and we need not jump through hoops to try to delete
25# it when configure exits.)
26tmpdir = meson.current_build_dir() / 'meson-private/temp'
27
28if get_option('qemu_suffix').startswith('/')
29  error('qemu_suffix cannot start with a /')
30endif
31
32qemu_confdir = get_option('sysconfdir') / get_option('qemu_suffix')
33qemu_datadir = get_option('datadir') / get_option('qemu_suffix')
34qemu_docdir = get_option('docdir') / get_option('qemu_suffix')
35qemu_moddir = get_option('libdir') / get_option('qemu_suffix')
36
37qemu_desktopdir = get_option('datadir') / 'applications'
38qemu_icondir = get_option('datadir') / 'icons'
39
40config_host_data = configuration_data()
41genh = []
42
43target_dirs = config_host['TARGET_DIRS'].split()
44have_user = false
45have_system = false
46foreach target : target_dirs
47  have_user = have_user or target.endswith('-user')
48  have_system = have_system or target.endswith('-softmmu')
49endforeach
50have_tools = 'CONFIG_TOOLS' in config_host
51have_block = have_system or have_tools
52
53python = import('python').find_installation()
54
55supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux']
56supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv32', 'riscv64', 'x86', 'x86_64',
57  'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64']
58
59cpu = host_machine.cpu_family()
60targetos = host_machine.system()
61
62if cpu in ['x86', 'x86_64']
63  kvm_targets = ['i386-softmmu', 'x86_64-softmmu']
64elif cpu == 'aarch64'
65  kvm_targets = ['aarch64-softmmu']
66elif cpu == 's390x'
67  kvm_targets = ['s390x-softmmu']
68elif cpu in ['ppc', 'ppc64']
69  kvm_targets = ['ppc-softmmu', 'ppc64-softmmu']
70elif cpu in ['mips', 'mips64']
71  kvm_targets = ['mips-softmmu', 'mipsel-softmmu', 'mips64-softmmu', 'mips64el-softmmu']
72else
73  kvm_targets = []
74endif
75
76accelerator_targets = { 'CONFIG_KVM': kvm_targets }
77if cpu in ['x86', 'x86_64', 'arm', 'aarch64']
78  # i368 emulator provides xenpv machine type for multiple architectures
79  accelerator_targets += {
80    'CONFIG_XEN': ['i386-softmmu', 'x86_64-softmmu'],
81  }
82endif
83if cpu in ['x86', 'x86_64']
84  accelerator_targets += {
85    'CONFIG_HAX': ['i386-softmmu', 'x86_64-softmmu'],
86    'CONFIG_HVF': ['x86_64-softmmu'],
87    'CONFIG_WHPX': ['i386-softmmu', 'x86_64-softmmu'],
88  }
89endif
90
91edk2_targets = [ 'arm-softmmu', 'aarch64-softmmu', 'i386-softmmu', 'x86_64-softmmu' ]
92install_edk2_blobs = false
93if get_option('install_blobs')
94  foreach target : target_dirs
95    install_edk2_blobs = install_edk2_blobs or target in edk2_targets
96  endforeach
97endif
98
99bzip2 = find_program('bzip2', required: install_edk2_blobs)
100
101##################
102# Compiler flags #
103##################
104
105# Specify linker-script with add_project_link_arguments so that it is not placed
106# within a linker --start-group/--end-group pair
107if 'CONFIG_FUZZ' in config_host
108   add_project_link_arguments(['-Wl,-T,',
109                               (meson.current_source_dir() / 'tests/qtest/fuzz/fork_fuzz.ld')],
110                              native: false, language: ['c', 'cpp', 'objc'])
111endif
112
113add_global_arguments(config_host['QEMU_CFLAGS'].split(),
114                     native: false, language: ['c', 'objc'])
115add_global_arguments(config_host['QEMU_CXXFLAGS'].split(),
116                     native: false, language: 'cpp')
117add_global_link_arguments(config_host['QEMU_LDFLAGS'].split(),
118                          native: false, language: ['c', 'cpp', 'objc'])
119
120if targetos == 'linux'
121  add_project_arguments('-isystem', meson.current_source_dir() / 'linux-headers',
122                        '-isystem', 'linux-headers',
123                        language: ['c', 'cpp'])
124endif
125
126add_project_arguments('-iquote', '.',
127                      '-iquote', meson.current_source_dir(),
128                      '-iquote', meson.current_source_dir() / 'include',
129                      '-iquote', meson.current_source_dir() / 'disas/libvixl',
130                      language: ['c', 'cpp', 'objc'])
131
132link_language = meson.get_external_property('link_language', 'cpp')
133if link_language == 'cpp'
134  add_languages('cpp', required: true, native: false)
135endif
136if host_machine.system() == 'darwin'
137  add_languages('objc', required: false, native: false)
138endif
139
140sparse = find_program('cgcc', required: get_option('sparse'))
141if sparse.found()
142  run_target('sparse',
143             command: [find_program('scripts/check_sparse.py'),
144                       'compile_commands.json', sparse.full_path(), '-Wbitwise',
145                       '-Wno-transparent-union', '-Wno-old-initializer',
146                       '-Wno-non-pointer-null'])
147endif
148
149###########################################
150# Target-specific checks and dependencies #
151###########################################
152
153if targetos != 'linux' and get_option('mpath').enabled()
154  error('Multipath is supported only on Linux')
155endif
156
157m = cc.find_library('m', required: false)
158util = cc.find_library('util', required: false)
159winmm = []
160socket = []
161version_res = []
162coref = []
163iokit = []
164emulator_link_args = []
165hvf = not_found
166if targetos == 'windows'
167  socket = cc.find_library('ws2_32')
168  winmm = cc.find_library('winmm')
169
170  win = import('windows')
171  version_res = win.compile_resources('version.rc',
172                                      depend_files: files('pc-bios/qemu-nsis.ico'),
173                                      include_directories: include_directories('.'))
174elif targetos == 'darwin'
175  coref = dependency('appleframeworks', modules: 'CoreFoundation')
176  iokit = dependency('appleframeworks', modules: 'IOKit')
177elif targetos == 'sunos'
178  socket = [cc.find_library('socket'),
179            cc.find_library('nsl'),
180            cc.find_library('resolv')]
181elif targetos == 'haiku'
182  socket = [cc.find_library('posix_error_mapper'),
183            cc.find_library('network'),
184            cc.find_library('bsd')]
185elif targetos == 'openbsd'
186  if not get_option('tcg').disabled() and target_dirs.length() > 0
187    # Disable OpenBSD W^X if available
188    emulator_link_args = cc.get_supported_link_arguments('-Wl,-z,wxneeded')
189  endif
190endif
191
192accelerators = []
193if not get_option('kvm').disabled() and targetos == 'linux'
194  accelerators += 'CONFIG_KVM'
195endif
196if not get_option('xen').disabled() and 'CONFIG_XEN_BACKEND' in config_host
197  accelerators += 'CONFIG_XEN'
198  have_xen_pci_passthrough = not get_option('xen_pci_passthrough').disabled() and targetos == 'linux'
199else
200  have_xen_pci_passthrough = false
201endif
202if not get_option('whpx').disabled() and targetos == 'windows'
203  if get_option('whpx').enabled() and host_machine.cpu() != 'x86_64'
204    error('WHPX requires 64-bit host')
205  elif cc.has_header('WinHvPlatform.h', required: get_option('whpx')) and \
206       cc.has_header('WinHvEmulation.h', required: get_option('whpx'))
207    accelerators += 'CONFIG_WHPX'
208  endif
209endif
210if not get_option('hvf').disabled()
211  hvf = dependency('appleframeworks', modules: 'Hypervisor',
212                   required: get_option('hvf'))
213  if hvf.found()
214    accelerators += 'CONFIG_HVF'
215  endif
216endif
217if not get_option('hax').disabled()
218  if get_option('hax').enabled() or targetos in ['windows', 'darwin', 'netbsd']
219    accelerators += 'CONFIG_HAX'
220  endif
221endif
222
223tcg_arch = config_host['ARCH']
224if not get_option('tcg').disabled()
225  if cpu not in supported_cpus
226    if get_option('tcg_interpreter')
227      warning('Unsupported CPU @0@, will use TCG with TCI (experimental)'.format(cpu))
228    else
229      error('Unsupported CPU @0@, try --enable-tcg-interpreter'.format(cpu))
230    endif
231  endif
232  if get_option('tcg_interpreter')
233    tcg_arch = 'tci'
234  elif config_host['ARCH'] == 'sparc64'
235    tcg_arch = 'sparc'
236  elif config_host['ARCH'] == 's390x'
237    tcg_arch = 's390'
238  elif config_host['ARCH'] in ['x86_64', 'x32']
239    tcg_arch = 'i386'
240  elif config_host['ARCH'] == 'ppc64'
241    tcg_arch = 'ppc'
242  elif config_host['ARCH'] in ['riscv32', 'riscv64']
243    tcg_arch = 'riscv'
244  endif
245  add_project_arguments('-iquote', meson.current_source_dir() / 'tcg' / tcg_arch,
246                        '-iquote', meson.current_source_dir() / 'accel/tcg',
247                        language: ['c', 'cpp', 'objc'])
248
249  accelerators += 'CONFIG_TCG'
250  config_host += { 'CONFIG_TCG': 'y' }
251endif
252
253if 'CONFIG_KVM' not in accelerators and get_option('kvm').enabled()
254  error('KVM not available on this platform')
255endif
256if 'CONFIG_HVF' not in accelerators and get_option('hvf').enabled()
257  error('HVF not available on this platform')
258endif
259if 'CONFIG_WHPX' not in accelerators and get_option('whpx').enabled()
260  error('WHPX not available on this platform')
261endif
262if not have_xen_pci_passthrough and get_option('xen_pci_passthrough').enabled()
263  if 'CONFIG_XEN' in accelerators
264    error('Xen PCI passthrough not available on this platform')
265  else
266    error('Xen PCI passthrough requested but Xen not enabled')
267  endif
268endif
269
270################
271# Dependencies #
272################
273
274# The path to glib.h is added to all compilation commands.  This was
275# grandfathered in from the QEMU Makefiles.
276add_project_arguments(config_host['GLIB_CFLAGS'].split(),
277                      native: false, language: ['c', 'cpp', 'objc'])
278glib = declare_dependency(compile_args: config_host['GLIB_CFLAGS'].split(),
279                          link_args: config_host['GLIB_LIBS'].split())
280# override glib dep with the configure results (for subprojects)
281meson.override_dependency('glib-2.0', glib)
282
283gio = not_found
284if 'CONFIG_GIO' in config_host
285  gio = declare_dependency(compile_args: config_host['GIO_CFLAGS'].split(),
286                           link_args: config_host['GIO_LIBS'].split())
287endif
288lttng = not_found
289if 'CONFIG_TRACE_UST' in config_host
290  lttng = declare_dependency(link_args: config_host['LTTNG_UST_LIBS'].split())
291endif
292urcubp = not_found
293if 'CONFIG_TRACE_UST' in config_host
294  urcubp = declare_dependency(link_args: config_host['URCU_BP_LIBS'].split())
295endif
296gcrypt = not_found
297if 'CONFIG_GCRYPT' in config_host
298  gcrypt = declare_dependency(compile_args: config_host['GCRYPT_CFLAGS'].split(),
299                              link_args: config_host['GCRYPT_LIBS'].split())
300endif
301nettle = not_found
302if 'CONFIG_NETTLE' in config_host
303  nettle = declare_dependency(compile_args: config_host['NETTLE_CFLAGS'].split(),
304                              link_args: config_host['NETTLE_LIBS'].split())
305endif
306gnutls = not_found
307if 'CONFIG_GNUTLS' in config_host
308  gnutls = declare_dependency(compile_args: config_host['GNUTLS_CFLAGS'].split(),
309                              link_args: config_host['GNUTLS_LIBS'].split())
310endif
311pixman = not_found
312if have_system or have_tools
313  pixman = dependency('pixman-1', required: have_system, version:'>=0.21.8',
314                      method: 'pkg-config', static: enable_static)
315endif
316pam = not_found
317if 'CONFIG_AUTH_PAM' in config_host
318  pam = cc.find_library('pam')
319endif
320libaio = cc.find_library('aio', required: false)
321zlib = dependency('zlib', required: true, static: enable_static)
322linux_io_uring = not_found
323if 'CONFIG_LINUX_IO_URING' in config_host
324  linux_io_uring = declare_dependency(compile_args: config_host['LINUX_IO_URING_CFLAGS'].split(),
325                                      link_args: config_host['LINUX_IO_URING_LIBS'].split())
326endif
327libxml2 = not_found
328if 'CONFIG_LIBXML2' in config_host
329  libxml2 = declare_dependency(compile_args: config_host['LIBXML2_CFLAGS'].split(),
330                               link_args: config_host['LIBXML2_LIBS'].split())
331endif
332libnfs = not_found
333if not get_option('libnfs').auto() or have_block
334  libnfs = dependency('libnfs', version: '>=1.9.3',
335                      required: get_option('libnfs'),
336                      method: 'pkg-config', static: enable_static)
337endif
338
339libattr_test = '''
340  #include <stddef.h>
341  #include <sys/types.h>
342  #ifdef CONFIG_LIBATTR
343  #include <attr/xattr.h>
344  #else
345  #include <sys/xattr.h>
346  #endif
347  int main(void) { getxattr(NULL, NULL, NULL, 0); setxattr(NULL, NULL, NULL, 0, 0); return 0; }'''
348
349libattr = not_found
350have_old_libattr = false
351if not get_option('attr').disabled()
352  if cc.links(libattr_test)
353    libattr = declare_dependency()
354  else
355    libattr = cc.find_library('attr', has_headers: ['attr/xattr.h'],
356                              required: get_option('attr'),
357                              static: enable_static)
358    if libattr.found() and not \
359      cc.links(libattr_test, dependencies: libattr, args: '-DCONFIG_LIBATTR')
360      libattr = not_found
361      if get_option('attr').enabled()
362        error('could not link libattr')
363      else
364        warning('could not link libattr, disabling')
365      endif
366    else
367      have_old_libattr = libattr.found()
368    endif
369  endif
370endif
371
372cocoa = dependency('appleframeworks', modules: 'Cocoa', required: get_option('cocoa'))
373if cocoa.found() and get_option('sdl').enabled()
374  error('Cocoa and SDL cannot be enabled at the same time')
375endif
376if cocoa.found() and get_option('gtk').enabled()
377  error('Cocoa and GTK+ cannot be enabled at the same time')
378endif
379
380seccomp = not_found
381if not get_option('seccomp').auto() or have_system or have_tools
382  seccomp = dependency('libseccomp', version: '>=2.3.0',
383                       required: get_option('seccomp'),
384                       method: 'pkg-config', static: enable_static)
385endif
386
387libcap_ng = not_found
388if not get_option('cap_ng').auto() or have_system or have_tools
389  libcap_ng = cc.find_library('cap-ng', has_headers: ['cap-ng.h'],
390                              required: get_option('cap_ng'),
391                              static: enable_static)
392endif
393if libcap_ng.found() and not cc.links('''
394   #include <cap-ng.h>
395   int main(void)
396   {
397     capng_capability_to_name(CAPNG_EFFECTIVE);
398     return 0;
399   }''', dependencies: libcap_ng)
400  libcap_ng = not_found
401  if get_option('cap_ng').enabled()
402    error('could not link libcap-ng')
403  else
404    warning('could not link libcap-ng, disabling')
405  endif
406endif
407
408if get_option('xkbcommon').auto() and not have_system and not have_tools
409  xkbcommon = not_found
410else
411  xkbcommon = dependency('xkbcommon', required: get_option('xkbcommon'),
412                         method: 'pkg-config', static: enable_static)
413endif
414vde = not_found
415if config_host.has_key('CONFIG_VDE')
416  vde = declare_dependency(link_args: config_host['VDE_LIBS'].split())
417endif
418pulse = not_found
419if 'CONFIG_LIBPULSE' in config_host
420  pulse = declare_dependency(compile_args: config_host['PULSE_CFLAGS'].split(),
421                             link_args: config_host['PULSE_LIBS'].split())
422endif
423alsa = not_found
424if 'CONFIG_ALSA' in config_host
425  alsa = declare_dependency(compile_args: config_host['ALSA_CFLAGS'].split(),
426                            link_args: config_host['ALSA_LIBS'].split())
427endif
428jack = not_found
429if 'CONFIG_LIBJACK' in config_host
430  jack = declare_dependency(link_args: config_host['JACK_LIBS'].split())
431endif
432spice = not_found
433spice_headers = not_found
434if 'CONFIG_SPICE' in config_host
435  spice = declare_dependency(compile_args: config_host['SPICE_CFLAGS'].split(),
436                             link_args: config_host['SPICE_LIBS'].split())
437  spice_headers = declare_dependency(compile_args: config_host['SPICE_CFLAGS'].split())
438endif
439rt = cc.find_library('rt', required: false)
440libdl = not_found
441if 'CONFIG_PLUGIN' in config_host
442  libdl = cc.find_library('dl', required: true)
443endif
444libiscsi = not_found
445if not get_option('libiscsi').auto() or have_block
446  libiscsi = dependency('libiscsi', version: '>=1.9.0',
447                         required: get_option('libiscsi'),
448                         method: 'pkg-config', static: enable_static)
449endif
450zstd = not_found
451if not get_option('zstd').auto() or have_block
452  zstd = dependency('libzstd', version: '>=1.4.0',
453                    required: get_option('zstd'),
454                    method: 'pkg-config', static: enable_static)
455endif
456gbm = not_found
457if 'CONFIG_GBM' in config_host
458  gbm = declare_dependency(compile_args: config_host['GBM_CFLAGS'].split(),
459                           link_args: config_host['GBM_LIBS'].split())
460endif
461virgl = not_found
462if 'CONFIG_VIRGL' in config_host
463  virgl = declare_dependency(compile_args: config_host['VIRGL_CFLAGS'].split(),
464                             link_args: config_host['VIRGL_LIBS'].split())
465endif
466curl = not_found
467if not get_option('curl').auto() or have_block
468  curl = dependency('libcurl', version: '>=7.29.0',
469                    method: 'pkg-config',
470                    required: get_option('curl'),
471                    static: enable_static)
472endif
473libudev = not_found
474if targetos == 'linux' and (have_system or have_tools)
475  libudev = dependency('libudev',
476                       method: 'pkg-config',
477                       required: get_option('libudev'),
478                       static: enable_static)
479endif
480
481mpathlibs = [libudev]
482mpathpersist = not_found
483mpathpersist_new_api = false
484if targetos == 'linux' and have_tools and not get_option('mpath').disabled()
485  mpath_test_source_new = '''
486    #include <libudev.h>
487    #include <mpath_persist.h>
488    unsigned mpath_mx_alloc_len = 1024;
489    int logsink;
490    static struct config *multipath_conf;
491    extern struct udev *udev;
492    extern struct config *get_multipath_config(void);
493    extern void put_multipath_config(struct config *conf);
494    struct udev *udev;
495    struct config *get_multipath_config(void) { return multipath_conf; }
496    void put_multipath_config(struct config *conf) { }
497    int main(void) {
498        udev = udev_new();
499        multipath_conf = mpath_lib_init();
500        return 0;
501    }'''
502  mpath_test_source_old = '''
503      #include <libudev.h>
504      #include <mpath_persist.h>
505      unsigned mpath_mx_alloc_len = 1024;
506      int logsink;
507      int main(void) {
508          struct udev *udev = udev_new();
509          mpath_lib_init(udev);
510          return 0;
511      }'''
512  libmpathpersist = cc.find_library('mpathpersist',
513                                    required: get_option('mpath'),
514                                    static: enable_static)
515  if libmpathpersist.found()
516    mpathlibs += libmpathpersist
517    if enable_static
518      mpathlibs += cc.find_library('devmapper',
519                                     required: get_option('mpath'),
520                                     static: enable_static)
521    endif
522    mpathlibs += cc.find_library('multipath',
523                                 required: get_option('mpath'),
524                                 static: enable_static)
525    foreach lib: mpathlibs
526      if not lib.found()
527        mpathlibs = []
528        break
529      endif
530    endforeach
531    if mpathlibs.length() == 0
532      msg = 'Dependencies missing for libmpathpersist'
533    elif cc.links(mpath_test_source_new, dependencies: mpathlibs)
534      mpathpersist = declare_dependency(dependencies: mpathlibs)
535      mpathpersist_new_api = true
536    elif cc.links(mpath_test_source_old, dependencies: mpathlibs)
537      mpathpersist = declare_dependency(dependencies: mpathlibs)
538    else
539      msg = 'Cannot detect libmpathpersist API'
540    endif
541    if not mpathpersist.found()
542      if get_option('mpath').enabled()
543        error(msg)
544      else
545        warning(msg + ', disabling')
546      endif
547    endif
548  endif
549endif
550
551iconv = not_found
552curses = not_found
553if have_system and not get_option('curses').disabled()
554  curses_test = '''
555    #include <locale.h>
556    #include <curses.h>
557    #include <wchar.h>
558    int main(void) {
559      wchar_t wch = L'w';
560      setlocale(LC_ALL, "");
561      resize_term(0, 0);
562      addwstr(L"wide chars\n");
563      addnwstr(&wch, 1);
564      add_wch(WACS_DEGREE);
565      return 0;
566    }'''
567
568  curses_dep_list = targetos == 'windows' ? ['ncurses', 'ncursesw'] : ['ncursesw']
569  foreach curses_dep : curses_dep_list
570    if not curses.found()
571      curses = dependency(curses_dep,
572                          required: false,
573                          method: 'pkg-config',
574                          static: enable_static)
575    endif
576  endforeach
577  msg = get_option('curses').enabled() ? 'curses library not found' : ''
578  curses_compile_args = ['-DNCURSES_WIDECHAR']
579  if curses.found()
580    if cc.links(curses_test, args: curses_compile_args, dependencies: [curses])
581      curses = declare_dependency(compile_args: curses_compile_args, dependencies: [curses])
582    else
583      msg = 'curses package not usable'
584      curses = not_found
585    endif
586  endif
587  if not curses.found()
588    has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
589    if targetos != 'windows' and not has_curses_h
590      message('Trying with /usr/include/ncursesw')
591      curses_compile_args += ['-I/usr/include/ncursesw']
592      has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
593    endif
594    if has_curses_h
595      curses_libname_list = (targetos == 'windows' ? ['pdcurses'] : ['ncursesw', 'cursesw'])
596      foreach curses_libname : curses_libname_list
597        libcurses = cc.find_library(curses_libname,
598                                    required: false,
599                                    static: enable_static)
600        if libcurses.found()
601          if cc.links(curses_test, args: curses_compile_args, dependencies: libcurses)
602            curses = declare_dependency(compile_args: curses_compile_args,
603                                        dependencies: [libcurses])
604            break
605          else
606            msg = 'curses library not usable'
607          endif
608        endif
609      endforeach
610    endif
611  endif
612  if not get_option('iconv').disabled()
613    foreach link_args : [ ['-liconv'], [] ]
614      # Programs will be linked with glib and this will bring in libiconv on FreeBSD.
615      # We need to use libiconv if available because mixing libiconv's headers with
616      # the system libc does not work.
617      # However, without adding glib to the dependencies -L/usr/local/lib will not be
618      # included in the command line and libiconv will not be found.
619      if cc.links('''
620        #include <iconv.h>
621        int main(void) {
622          iconv_t conv = iconv_open("WCHAR_T", "UCS-2");
623          return conv != (iconv_t) -1;
624        }''', args: config_host['GLIB_CFLAGS'].split() + config_host['GLIB_LIBS'].split() + link_args)
625        iconv = declare_dependency(link_args: link_args, dependencies: glib)
626        break
627      endif
628    endforeach
629  endif
630  if curses.found() and not iconv.found()
631    if get_option('iconv').enabled()
632      error('iconv not available')
633    endif
634    msg = 'iconv required for curses UI but not available'
635    curses = not_found
636  endif
637  if not curses.found() and msg != ''
638    if get_option('curses').enabled()
639      error(msg)
640    else
641      warning(msg + ', disabling')
642    endif
643  endif
644endif
645
646brlapi = not_found
647if not get_option('brlapi').auto() or have_system
648  brlapi = cc.find_library('brlapi', has_headers: ['brlapi.h'],
649                         required: get_option('brlapi'),
650                         static: enable_static)
651  if brlapi.found() and not cc.links('''
652     #include <brlapi.h>
653     #include <stddef.h>
654     int main(void) { return brlapi__openConnection (NULL, NULL, NULL); }''', dependencies: brlapi)
655    brlapi = not_found
656    if get_option('brlapi').enabled()
657      error('could not link brlapi')
658    else
659      warning('could not link brlapi, disabling')
660    endif
661  endif
662endif
663
664sdl = not_found
665if not get_option('sdl').auto() or (have_system and not cocoa.found())
666  sdl = dependency('sdl2', required: get_option('sdl'), static: enable_static)
667  sdl_image = not_found
668endif
669if sdl.found()
670  # work around 2.0.8 bug
671  sdl = declare_dependency(compile_args: '-Wno-undef',
672                           dependencies: sdl)
673  sdl_image = dependency('SDL2_image', required: get_option('sdl_image'),
674                         method: 'pkg-config', static: enable_static)
675else
676  if get_option('sdl_image').enabled()
677    error('sdl-image required, but SDL was @0@'.format(
678          get_option('sdl').disabled() ? 'disabled' : 'not found'))
679  endif
680  sdl_image = not_found
681endif
682
683rbd = not_found
684if not get_option('rbd').auto() or have_block
685  librados = cc.find_library('rados', required: get_option('rbd'),
686                             static: enable_static)
687  librbd = cc.find_library('rbd', has_headers: ['rbd/librbd.h'],
688                           required: get_option('rbd'),
689                           static: enable_static)
690  if librados.found() and librbd.found() and cc.links('''
691    #include <stdio.h>
692    #include <rbd/librbd.h>
693    int main(void) {
694      rados_t cluster;
695      rados_create(&cluster, NULL);
696      return 0;
697    }''', dependencies: [librbd, librados])
698    rbd = declare_dependency(dependencies: [librbd, librados])
699  endif
700endif
701
702glusterfs = not_found
703glusterfs_ftruncate_has_stat = false
704glusterfs_iocb_has_stat = false
705if not get_option('glusterfs').auto() or have_block
706  glusterfs = dependency('glusterfs-api', version: '>=3',
707                         required: get_option('glusterfs'),
708                         method: 'pkg-config', static: enable_static)
709  if glusterfs.found()
710    glusterfs_ftruncate_has_stat = cc.links('''
711      #include <glusterfs/api/glfs.h>
712
713      int
714      main(void)
715      {
716          /* new glfs_ftruncate() passes two additional args */
717          return glfs_ftruncate(NULL, 0, NULL, NULL);
718      }
719    ''', dependencies: glusterfs)
720    glusterfs_iocb_has_stat = cc.links('''
721      #include <glusterfs/api/glfs.h>
722
723      /* new glfs_io_cbk() passes two additional glfs_stat structs */
724      static void
725      glusterfs_iocb(glfs_fd_t *fd, ssize_t ret, struct glfs_stat *prestat, struct glfs_stat *poststat, void *data)
726      {}
727
728      int
729      main(void)
730      {
731          glfs_io_cbk iocb = &glusterfs_iocb;
732          iocb(NULL, 0 , NULL, NULL, NULL);
733          return 0;
734      }
735    ''', dependencies: glusterfs)
736  endif
737endif
738libssh = not_found
739if 'CONFIG_LIBSSH' in config_host
740  libssh = declare_dependency(compile_args: config_host['LIBSSH_CFLAGS'].split(),
741                              link_args: config_host['LIBSSH_LIBS'].split())
742endif
743libbzip2 = not_found
744if not get_option('bzip2').auto() or have_block
745  libbzip2 = cc.find_library('bz2', has_headers: ['bzlib.h'],
746                             required: get_option('bzip2'),
747                             static: enable_static)
748  if libbzip2.found() and not cc.links('''
749     #include <bzlib.h>
750     int main(void) { BZ2_bzlibVersion(); return 0; }''', dependencies: libbzip2)
751    libbzip2 = not_found
752    if get_option('bzip2').enabled()
753      error('could not link libbzip2')
754    else
755      warning('could not link libbzip2, disabling')
756    endif
757  endif
758endif
759
760liblzfse = not_found
761if not get_option('lzfse').auto() or have_block
762  liblzfse = cc.find_library('lzfse', has_headers: ['lzfse.h'],
763                             required: get_option('lzfse'),
764                             static: enable_static)
765endif
766if liblzfse.found() and not cc.links('''
767   #include <lzfse.h>
768   int main(void) { lzfse_decode_scratch_size(); return 0; }''', dependencies: liblzfse)
769  liblzfse = not_found
770  if get_option('lzfse').enabled()
771    error('could not link liblzfse')
772  else
773    warning('could not link liblzfse, disabling')
774  endif
775endif
776
777oss = not_found
778if 'CONFIG_AUDIO_OSS' in config_host
779  oss = declare_dependency(link_args: config_host['OSS_LIBS'].split())
780endif
781dsound = not_found
782if 'CONFIG_AUDIO_DSOUND' in config_host
783  dsound = declare_dependency(link_args: config_host['DSOUND_LIBS'].split())
784endif
785coreaudio = not_found
786if 'CONFIG_AUDIO_COREAUDIO' in config_host
787  coreaudio = declare_dependency(link_args: config_host['COREAUDIO_LIBS'].split())
788endif
789opengl = not_found
790if 'CONFIG_OPENGL' in config_host
791  opengl = declare_dependency(compile_args: config_host['OPENGL_CFLAGS'].split(),
792                              link_args: config_host['OPENGL_LIBS'].split())
793endif
794
795gtk = not_found
796gtkx11 = not_found
797if not get_option('gtk').auto() or (have_system and not cocoa.found())
798  gtk = dependency('gtk+-3.0', version: '>=3.22.0',
799                   method: 'pkg-config',
800                   required: get_option('gtk'),
801                   static: enable_static)
802  if gtk.found()
803    gtkx11 = dependency('gtk+-x11-3.0', version: '>=3.22.0',
804                        method: 'pkg-config',
805                        required: false,
806                        static: enable_static)
807    gtk = declare_dependency(dependencies: [gtk, gtkx11])
808  endif
809endif
810
811vte = not_found
812if 'CONFIG_VTE' in config_host
813  vte = declare_dependency(compile_args: config_host['VTE_CFLAGS'].split(),
814                           link_args: config_host['VTE_LIBS'].split())
815endif
816x11 = not_found
817if gtkx11.found() or 'lm32-softmmu' in target_dirs
818  x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found(),
819                   static: enable_static)
820endif
821vnc = not_found
822png = not_found
823jpeg = not_found
824sasl = not_found
825if get_option('vnc').enabled()
826  vnc = declare_dependency() # dummy dependency
827  png = dependency('libpng', required: get_option('vnc_png'),
828                   method: 'pkg-config', static: enable_static)
829  jpeg = dependency('libjpeg', required: get_option('vnc_jpeg'),
830                    method: 'pkg-config', static: enable_static)
831  sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'],
832                         required: get_option('vnc_sasl'),
833                         static: enable_static)
834  if sasl.found()
835    sasl = declare_dependency(dependencies: sasl,
836                              compile_args: '-DSTRUCT_IOVEC_DEFINED')
837  endif
838endif
839
840snappy = not_found
841if not get_option('snappy').auto() or have_system
842  snappy = cc.find_library('snappy', has_headers: ['snappy-c.h'],
843                           required: get_option('snappy'),
844                           static: enable_static)
845endif
846if snappy.found() and not cc.links('''
847   #include <snappy-c.h>
848   int main(void) { snappy_max_compressed_length(4096); return 0; }''', dependencies: snappy)
849  snappy = not_found
850  if get_option('snappy').enabled()
851    error('could not link libsnappy')
852  else
853    warning('could not link libsnappy, disabling')
854  endif
855endif
856
857lzo = not_found
858if not get_option('lzo').auto() or have_system
859  lzo = cc.find_library('lzo2', has_headers: ['lzo/lzo1x.h'],
860                        required: get_option('lzo'),
861                        static: enable_static)
862endif
863if lzo.found() and not cc.links('''
864   #include <lzo/lzo1x.h>
865   int main(void) { lzo_version(); return 0; }''', dependencies: lzo)
866  lzo = not_found
867  if get_option('lzo').enabled()
868    error('could not link liblzo2')
869  else
870    warning('could not link liblzo2, disabling')
871  endif
872endif
873
874rdma = not_found
875if 'CONFIG_RDMA' in config_host
876  rdma = declare_dependency(link_args: config_host['RDMA_LIBS'].split())
877endif
878numa = not_found
879if 'CONFIG_NUMA' in config_host
880  numa = declare_dependency(link_args: config_host['NUMA_LIBS'].split())
881endif
882xen = not_found
883if 'CONFIG_XEN_BACKEND' in config_host
884  xen = declare_dependency(compile_args: config_host['XEN_CFLAGS'].split(),
885                           link_args: config_host['XEN_LIBS'].split())
886endif
887cacard = not_found
888if 'CONFIG_SMARTCARD' in config_host
889  cacard = declare_dependency(compile_args: config_host['SMARTCARD_CFLAGS'].split(),
890                              link_args: config_host['SMARTCARD_LIBS'].split())
891endif
892u2f = not_found
893if have_system
894  u2f = dependency('u2f-emu', required: get_option('u2f'),
895                   method: 'pkg-config',
896                   static: enable_static)
897endif
898usbredir = not_found
899if 'CONFIG_USB_REDIR' in config_host
900  usbredir = declare_dependency(compile_args: config_host['USB_REDIR_CFLAGS'].split(),
901                                link_args: config_host['USB_REDIR_LIBS'].split())
902endif
903libusb = not_found
904if 'CONFIG_USB_LIBUSB' in config_host
905  libusb = declare_dependency(compile_args: config_host['LIBUSB_CFLAGS'].split(),
906                              link_args: config_host['LIBUSB_LIBS'].split())
907endif
908libpmem = not_found
909if 'CONFIG_LIBPMEM' in config_host
910  libpmem = declare_dependency(compile_args: config_host['LIBPMEM_CFLAGS'].split(),
911                               link_args: config_host['LIBPMEM_LIBS'].split())
912endif
913libdaxctl = not_found
914if 'CONFIG_LIBDAXCTL' in config_host
915  libdaxctl = declare_dependency(link_args: config_host['LIBDAXCTL_LIBS'].split())
916endif
917tasn1 = not_found
918if 'CONFIG_TASN1' in config_host
919  tasn1 = declare_dependency(compile_args: config_host['TASN1_CFLAGS'].split(),
920                             link_args: config_host['TASN1_LIBS'].split())
921endif
922keyutils = dependency('libkeyutils', required: false,
923                      method: 'pkg-config', static: enable_static)
924
925has_gettid = cc.has_function('gettid')
926
927# Malloc tests
928
929malloc = []
930if get_option('malloc') == 'system'
931  has_malloc_trim = \
932    not get_option('malloc_trim').disabled() and \
933    cc.links('''#include <malloc.h>
934                int main(void) { malloc_trim(0); return 0; }''')
935else
936  has_malloc_trim = false
937  malloc = cc.find_library(get_option('malloc'), required: true)
938endif
939if not has_malloc_trim and get_option('malloc_trim').enabled()
940  if get_option('malloc') == 'system'
941    error('malloc_trim not available on this platform.')
942  else
943    error('malloc_trim not available with non-libc memory allocator')
944  endif
945endif
946
947# Check whether the glibc provides statx()
948
949statx_test = '''
950  #ifndef _GNU_SOURCE
951  #define _GNU_SOURCE
952  #endif
953  #include <sys/stat.h>
954  int main(void) {
955    struct statx statxbuf;
956    statx(0, "", 0, STATX_BASIC_STATS, &statxbuf);
957    return 0;
958  }'''
959
960has_statx = cc.links(statx_test)
961
962have_vhost_user_blk_server = (targetos == 'linux' and
963    'CONFIG_VHOST_USER' in config_host)
964
965if get_option('vhost_user_blk_server').enabled()
966    if targetos != 'linux'
967        error('vhost_user_blk_server requires linux')
968    elif 'CONFIG_VHOST_USER' not in config_host
969        error('vhost_user_blk_server requires vhost-user support')
970    endif
971elif get_option('vhost_user_blk_server').disabled() or not have_system
972    have_vhost_user_blk_server = false
973endif
974
975
976if get_option('fuse').disabled() and get_option('fuse_lseek').enabled()
977  error('Cannot enable fuse-lseek while fuse is disabled')
978endif
979
980fuse = dependency('fuse3', required: get_option('fuse'),
981                  version: '>=3.1', method: 'pkg-config',
982                  static: enable_static)
983
984fuse_lseek = not_found
985if not get_option('fuse_lseek').disabled()
986  if fuse.version().version_compare('>=3.8')
987    # Dummy dependency
988    fuse_lseek = declare_dependency()
989  elif get_option('fuse_lseek').enabled()
990    if fuse.found()
991      error('fuse-lseek requires libfuse >=3.8, found ' + fuse.version())
992    else
993      error('fuse-lseek requires libfuse, which was not found')
994    endif
995  endif
996endif
997
998if get_option('cfi')
999  cfi_flags=[]
1000  # Check for dependency on LTO
1001  if not get_option('b_lto')
1002    error('Selected Control-Flow Integrity but LTO is disabled')
1003  endif
1004  if config_host.has_key('CONFIG_MODULES')
1005    error('Selected Control-Flow Integrity is not compatible with modules')
1006  endif
1007  # Check for cfi flags. CFI requires LTO so we can't use
1008  # get_supported_arguments, but need a more complex "compiles" which allows
1009  # custom arguments
1010  if cc.compiles('int main () { return 0; }', name: '-fsanitize=cfi-icall',
1011                 args: ['-flto', '-fsanitize=cfi-icall'] )
1012    cfi_flags += '-fsanitize=cfi-icall'
1013  else
1014    error('-fsanitize=cfi-icall is not supported by the compiler')
1015  endif
1016  if cc.compiles('int main () { return 0; }',
1017                 name: '-fsanitize-cfi-icall-generalize-pointers',
1018                 args: ['-flto', '-fsanitize=cfi-icall',
1019                        '-fsanitize-cfi-icall-generalize-pointers'] )
1020    cfi_flags += '-fsanitize-cfi-icall-generalize-pointers'
1021  else
1022    error('-fsanitize-cfi-icall-generalize-pointers is not supported by the compiler')
1023  endif
1024  if get_option('cfi_debug')
1025    if cc.compiles('int main () { return 0; }',
1026                   name: '-fno-sanitize-trap=cfi-icall',
1027                   args: ['-flto', '-fsanitize=cfi-icall',
1028                          '-fno-sanitize-trap=cfi-icall'] )
1029      cfi_flags += '-fno-sanitize-trap=cfi-icall'
1030    else
1031      error('-fno-sanitize-trap=cfi-icall is not supported by the compiler')
1032    endif
1033  endif
1034  add_global_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
1035  add_global_link_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
1036endif
1037
1038#################
1039# config-host.h #
1040#################
1041
1042have_virtfs = (targetos == 'linux' and
1043    have_system and
1044    libattr.found() and
1045    libcap_ng.found())
1046
1047have_virtfs_proxy_helper = have_virtfs and have_tools
1048
1049if get_option('virtfs').enabled()
1050  if not have_virtfs
1051    if targetos != 'linux'
1052      error('virtio-9p (virtfs) requires Linux')
1053    elif not libcap_ng.found() or not libattr.found()
1054      error('virtio-9p (virtfs) requires libcap-ng-devel and libattr-devel')
1055    elif not have_system
1056      error('virtio-9p (virtfs) needs system emulation support')
1057    endif
1058  endif
1059elif get_option('virtfs').disabled()
1060  have_virtfs = false
1061endif
1062
1063config_host_data.set_quoted('CONFIG_BINDIR', get_option('prefix') / get_option('bindir'))
1064config_host_data.set_quoted('CONFIG_PREFIX', get_option('prefix'))
1065config_host_data.set_quoted('CONFIG_QEMU_CONFDIR', get_option('prefix') / qemu_confdir)
1066config_host_data.set_quoted('CONFIG_QEMU_DATADIR', get_option('prefix') / qemu_datadir)
1067config_host_data.set_quoted('CONFIG_QEMU_DESKTOPDIR', get_option('prefix') / qemu_desktopdir)
1068config_host_data.set_quoted('CONFIG_QEMU_FIRMWAREPATH', get_option('qemu_firmwarepath'))
1069config_host_data.set_quoted('CONFIG_QEMU_HELPERDIR', get_option('prefix') / get_option('libexecdir'))
1070config_host_data.set_quoted('CONFIG_QEMU_ICONDIR', get_option('prefix') / qemu_icondir)
1071config_host_data.set_quoted('CONFIG_QEMU_LOCALEDIR', get_option('prefix') / get_option('localedir'))
1072config_host_data.set_quoted('CONFIG_QEMU_LOCALSTATEDIR', get_option('prefix') / get_option('localstatedir'))
1073config_host_data.set_quoted('CONFIG_QEMU_MODDIR', get_option('prefix') / qemu_moddir)
1074config_host_data.set_quoted('CONFIG_SYSCONFDIR', get_option('prefix') / get_option('sysconfdir'))
1075
1076config_host_data.set('CONFIG_ATTR', libattr.found())
1077config_host_data.set('CONFIG_BRLAPI', brlapi.found())
1078config_host_data.set('CONFIG_COCOA', cocoa.found())
1079config_host_data.set('CONFIG_LIBUDEV', libudev.found())
1080config_host_data.set('CONFIG_LZO', lzo.found())
1081config_host_data.set('CONFIG_MPATH', mpathpersist.found())
1082config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api)
1083config_host_data.set('CONFIG_CURL', curl.found())
1084config_host_data.set('CONFIG_CURSES', curses.found())
1085config_host_data.set('CONFIG_GLUSTERFS', glusterfs.found())
1086if glusterfs.found()
1087  config_host_data.set('CONFIG_GLUSTERFS_XLATOR_OPT', glusterfs.version().version_compare('>=4'))
1088  config_host_data.set('CONFIG_GLUSTERFS_DISCARD', glusterfs.version().version_compare('>=5'))
1089  config_host_data.set('CONFIG_GLUSTERFS_FALLOCATE', glusterfs.version().version_compare('>=6'))
1090  config_host_data.set('CONFIG_GLUSTERFS_ZEROFILL', glusterfs.version().version_compare('>=6'))
1091  config_host_data.set('CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT', glusterfs_ftruncate_has_stat)
1092  config_host_data.set('CONFIG_GLUSTERFS_IOCB_HAS_STAT', glusterfs_iocb_has_stat)
1093endif
1094config_host_data.set('CONFIG_GTK', gtk.found())
1095config_host_data.set('CONFIG_LIBATTR', have_old_libattr)
1096config_host_data.set('CONFIG_LIBCAP_NG', libcap_ng.found())
1097config_host_data.set('CONFIG_LIBISCSI', libiscsi.found())
1098config_host_data.set('CONFIG_LIBNFS', libnfs.found())
1099config_host_data.set('CONFIG_RBD', rbd.found())
1100config_host_data.set('CONFIG_SDL', sdl.found())
1101config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
1102config_host_data.set('CONFIG_SECCOMP', seccomp.found())
1103config_host_data.set('CONFIG_SNAPPY', snappy.found())
1104config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
1105config_host_data.set('CONFIG_VNC', vnc.found())
1106config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
1107config_host_data.set('CONFIG_VNC_PNG', png.found())
1108config_host_data.set('CONFIG_VNC_SASL', sasl.found())
1109config_host_data.set('CONFIG_VIRTFS', have_virtfs)
1110config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
1111config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
1112config_host_data.set('CONFIG_GETTID', has_gettid)
1113config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
1114config_host_data.set('CONFIG_STATX', has_statx)
1115config_host_data.set('CONFIG_ZSTD', zstd.found())
1116config_host_data.set('CONFIG_FUSE', fuse.found())
1117config_host_data.set('CONFIG_FUSE_LSEEK', fuse_lseek.found())
1118config_host_data.set('CONFIG_X11', x11.found())
1119config_host_data.set('CONFIG_CFI', get_option('cfi'))
1120config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
1121config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
1122config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
1123config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
1124
1125config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h'))
1126config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
1127config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
1128config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
1129config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
1130config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
1131
1132config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
1133
1134ignored = ['CONFIG_QEMU_INTERP_PREFIX'] # actually per-target
1135arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
1136strings = ['HOST_DSOSUF', 'CONFIG_IASL']
1137foreach k, v: config_host
1138  if ignored.contains(k)
1139    # do nothing
1140  elif arrays.contains(k)
1141    if v != ''
1142      v = '"' + '", "'.join(v.split()) + '", '
1143    endif
1144    config_host_data.set(k, v)
1145  elif k == 'ARCH'
1146    config_host_data.set('HOST_' + v.to_upper(), 1)
1147  elif strings.contains(k)
1148    if not k.startswith('CONFIG_')
1149      k = 'CONFIG_' + k.to_upper()
1150    endif
1151    config_host_data.set_quoted(k, v)
1152  elif k.startswith('CONFIG_') or k.startswith('HAVE_') or k.startswith('HOST_')
1153    config_host_data.set(k, v == 'y' ? 1 : v)
1154  endif
1155endforeach
1156
1157########################
1158# Target configuration #
1159########################
1160
1161minikconf = find_program('scripts/minikconf.py')
1162config_all = {}
1163config_all_devices = {}
1164config_all_disas = {}
1165config_devices_mak_list = []
1166config_devices_h = {}
1167config_target_h = {}
1168config_target_mak = {}
1169
1170disassemblers = {
1171  'alpha' : ['CONFIG_ALPHA_DIS'],
1172  'arm' : ['CONFIG_ARM_DIS'],
1173  'avr' : ['CONFIG_AVR_DIS'],
1174  'cris' : ['CONFIG_CRIS_DIS'],
1175  'hppa' : ['CONFIG_HPPA_DIS'],
1176  'i386' : ['CONFIG_I386_DIS'],
1177  'x86_64' : ['CONFIG_I386_DIS'],
1178  'x32' : ['CONFIG_I386_DIS'],
1179  'lm32' : ['CONFIG_LM32_DIS'],
1180  'm68k' : ['CONFIG_M68K_DIS'],
1181  'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
1182  'mips' : ['CONFIG_MIPS_DIS'],
1183  'moxie' : ['CONFIG_MOXIE_DIS'],
1184  'nios2' : ['CONFIG_NIOS2_DIS'],
1185  'or1k' : ['CONFIG_OPENRISC_DIS'],
1186  'ppc' : ['CONFIG_PPC_DIS'],
1187  'riscv' : ['CONFIG_RISCV_DIS'],
1188  'rx' : ['CONFIG_RX_DIS'],
1189  's390' : ['CONFIG_S390_DIS'],
1190  'sh4' : ['CONFIG_SH4_DIS'],
1191  'sparc' : ['CONFIG_SPARC_DIS'],
1192  'xtensa' : ['CONFIG_XTENSA_DIS'],
1193}
1194if link_language == 'cpp'
1195  disassemblers += {
1196    'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
1197    'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
1198    'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
1199  }
1200endif
1201
1202host_kconfig = \
1203  ('CONFIG_TPM' in config_host ? ['CONFIG_TPM=y'] : []) + \
1204  ('CONFIG_SPICE' in config_host ? ['CONFIG_SPICE=y'] : []) + \
1205  ('CONFIG_IVSHMEM' in config_host ? ['CONFIG_IVSHMEM=y'] : []) + \
1206  ('CONFIG_OPENGL' in config_host ? ['CONFIG_OPENGL=y'] : []) + \
1207  (x11.found() ? ['CONFIG_X11=y'] : []) + \
1208  ('CONFIG_VHOST_USER' in config_host ? ['CONFIG_VHOST_USER=y'] : []) + \
1209  ('CONFIG_VHOST_VDPA' in config_host ? ['CONFIG_VHOST_VDPA=y'] : []) + \
1210  ('CONFIG_VHOST_KERNEL' in config_host ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
1211  (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
1212  ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \
1213  ('CONFIG_PVRDMA' in config_host ? ['CONFIG_PVRDMA=y'] : [])
1214
1215ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
1216
1217default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
1218actual_target_dirs = []
1219fdt_required = []
1220foreach target : target_dirs
1221  config_target = { 'TARGET_NAME': target.split('-')[0] }
1222  if target.endswith('linux-user')
1223    if targetos != 'linux'
1224      if default_targets
1225        continue
1226      endif
1227      error('Target @0@ is only available on a Linux host'.format(target))
1228    endif
1229    config_target += { 'CONFIG_LINUX_USER': 'y' }
1230  elif target.endswith('bsd-user')
1231    if 'CONFIG_BSD' not in config_host
1232      if default_targets
1233        continue
1234      endif
1235      error('Target @0@ is only available on a BSD host'.format(target))
1236    endif
1237    config_target += { 'CONFIG_BSD_USER': 'y' }
1238  elif target.endswith('softmmu')
1239    config_target += { 'CONFIG_SOFTMMU': 'y' }
1240  endif
1241  if target.endswith('-user')
1242    config_target += {
1243      'CONFIG_USER_ONLY': 'y',
1244      'CONFIG_QEMU_INTERP_PREFIX':
1245        config_host['CONFIG_QEMU_INTERP_PREFIX'].format(config_target['TARGET_NAME'])
1246    }
1247  endif
1248
1249  accel_kconfig = []
1250  foreach sym: accelerators
1251    if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
1252      config_target += { sym: 'y' }
1253      config_all += { sym: 'y' }
1254      if sym == 'CONFIG_TCG' and tcg_arch == 'tci'
1255        config_target += { 'CONFIG_TCG_INTERPRETER': 'y' }
1256      elif sym == 'CONFIG_XEN' and have_xen_pci_passthrough
1257        config_target += { 'CONFIG_XEN_PCI_PASSTHROUGH': 'y' }
1258      endif
1259      accel_kconfig += [ sym + '=y' ]
1260    endif
1261  endforeach
1262  if accel_kconfig.length() == 0
1263    if default_targets
1264      continue
1265    endif
1266    error('No accelerator available for target @0@'.format(target))
1267  endif
1268
1269  actual_target_dirs += target
1270  config_target += keyval.load('default-configs/targets' / target + '.mak')
1271  config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
1272
1273  if 'TARGET_NEED_FDT' in config_target
1274    fdt_required += target
1275  endif
1276
1277  # Add default keys
1278  if 'TARGET_BASE_ARCH' not in config_target
1279    config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
1280  endif
1281  if 'TARGET_ABI_DIR' not in config_target
1282    config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
1283  endif
1284
1285  foreach k, v: disassemblers
1286    if config_host['ARCH'].startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
1287      foreach sym: v
1288        config_target += { sym: 'y' }
1289        config_all_disas += { sym: 'y' }
1290      endforeach
1291    endif
1292  endforeach
1293
1294  config_target_data = configuration_data()
1295  foreach k, v: config_target
1296    if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
1297      # do nothing
1298    elif ignored.contains(k)
1299      # do nothing
1300    elif k == 'TARGET_BASE_ARCH'
1301      # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
1302      # not used to select files from sourcesets.
1303      config_target_data.set('TARGET_' + v.to_upper(), 1)
1304    elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
1305      config_target_data.set_quoted(k, v)
1306    elif v == 'y'
1307      config_target_data.set(k, 1)
1308    else
1309      config_target_data.set(k, v)
1310    endif
1311  endforeach
1312  config_target_h += {target: configure_file(output: target + '-config-target.h',
1313                                               configuration: config_target_data)}
1314
1315  if target.endswith('-softmmu')
1316    config_devices_mak = target + '-config-devices.mak'
1317    config_devices_mak = configure_file(
1318      input: ['default-configs/devices' / target + '.mak', 'Kconfig'],
1319      output: config_devices_mak,
1320      depfile: config_devices_mak + '.d',
1321      capture: true,
1322      command: [minikconf,
1323                get_option('default_devices') ? '--defconfig' : '--allnoconfig',
1324                config_devices_mak, '@DEPFILE@', '@INPUT@',
1325                host_kconfig, accel_kconfig])
1326
1327    config_devices_data = configuration_data()
1328    config_devices = keyval.load(config_devices_mak)
1329    foreach k, v: config_devices
1330      config_devices_data.set(k, 1)
1331    endforeach
1332    config_devices_mak_list += config_devices_mak
1333    config_devices_h += {target: configure_file(output: target + '-config-devices.h',
1334                                                configuration: config_devices_data)}
1335    config_target += config_devices
1336    config_all_devices += config_devices
1337  endif
1338  config_target_mak += {target: config_target}
1339endforeach
1340target_dirs = actual_target_dirs
1341
1342# This configuration is used to build files that are shared by
1343# multiple binaries, and then extracted out of the "common"
1344# static_library target.
1345#
1346# We do not use all_sources()/all_dependencies(), because it would
1347# build literally all source files, including devices only used by
1348# targets that are not built for this compilation.  The CONFIG_ALL
1349# pseudo symbol replaces it.
1350
1351config_all += config_all_devices
1352config_all += config_host
1353config_all += config_all_disas
1354config_all += {
1355  'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'),
1356  'CONFIG_SOFTMMU': have_system,
1357  'CONFIG_USER_ONLY': have_user,
1358  'CONFIG_ALL': true,
1359}
1360
1361##############
1362# Submodules #
1363##############
1364
1365capstone = not_found
1366capstone_opt = get_option('capstone')
1367if capstone_opt in ['enabled', 'auto', 'system']
1368  have_internal = fs.exists(meson.current_source_dir() / 'capstone/Makefile')
1369  capstone = dependency('capstone', version: '>=4.0',
1370                        static: enable_static, method: 'pkg-config',
1371                        required: capstone_opt == 'system' or
1372                                  capstone_opt == 'enabled' and not have_internal)
1373  if capstone.found()
1374    capstone_opt = 'system'
1375  elif have_internal
1376    capstone_opt = 'internal'
1377  else
1378    capstone_opt = 'disabled'
1379  endif
1380endif
1381if capstone_opt == 'internal'
1382  capstone_data = configuration_data()
1383  capstone_data.set('CAPSTONE_USE_SYS_DYN_MEM', '1')
1384
1385  capstone_files = files(
1386    'capstone/cs.c',
1387    'capstone/MCInst.c',
1388    'capstone/MCInstrDesc.c',
1389    'capstone/MCRegisterInfo.c',
1390    'capstone/SStream.c',
1391    'capstone/utils.c'
1392  )
1393
1394  if 'CONFIG_ARM_DIS' in config_all_disas
1395    capstone_data.set('CAPSTONE_HAS_ARM', '1')
1396    capstone_files += files(
1397      'capstone/arch/ARM/ARMDisassembler.c',
1398      'capstone/arch/ARM/ARMInstPrinter.c',
1399      'capstone/arch/ARM/ARMMapping.c',
1400      'capstone/arch/ARM/ARMModule.c'
1401    )
1402  endif
1403
1404  # FIXME: This config entry currently depends on a c++ compiler.
1405  # Which is needed for building libvixl, but not for capstone.
1406  if 'CONFIG_ARM_A64_DIS' in config_all_disas
1407    capstone_data.set('CAPSTONE_HAS_ARM64', '1')
1408    capstone_files += files(
1409      'capstone/arch/AArch64/AArch64BaseInfo.c',
1410      'capstone/arch/AArch64/AArch64Disassembler.c',
1411      'capstone/arch/AArch64/AArch64InstPrinter.c',
1412      'capstone/arch/AArch64/AArch64Mapping.c',
1413      'capstone/arch/AArch64/AArch64Module.c'
1414    )
1415  endif
1416
1417  if 'CONFIG_PPC_DIS' in config_all_disas
1418    capstone_data.set('CAPSTONE_HAS_POWERPC', '1')
1419    capstone_files += files(
1420      'capstone/arch/PowerPC/PPCDisassembler.c',
1421      'capstone/arch/PowerPC/PPCInstPrinter.c',
1422      'capstone/arch/PowerPC/PPCMapping.c',
1423      'capstone/arch/PowerPC/PPCModule.c'
1424    )
1425  endif
1426
1427  if 'CONFIG_S390_DIS' in config_all_disas
1428    capstone_data.set('CAPSTONE_HAS_SYSZ', '1')
1429    capstone_files += files(
1430      'capstone/arch/SystemZ/SystemZDisassembler.c',
1431      'capstone/arch/SystemZ/SystemZInstPrinter.c',
1432      'capstone/arch/SystemZ/SystemZMapping.c',
1433      'capstone/arch/SystemZ/SystemZModule.c',
1434      'capstone/arch/SystemZ/SystemZMCTargetDesc.c'
1435    )
1436  endif
1437
1438  if 'CONFIG_I386_DIS' in config_all_disas
1439    capstone_data.set('CAPSTONE_HAS_X86', 1)
1440    capstone_files += files(
1441      'capstone/arch/X86/X86Disassembler.c',
1442      'capstone/arch/X86/X86DisassemblerDecoder.c',
1443      'capstone/arch/X86/X86ATTInstPrinter.c',
1444      'capstone/arch/X86/X86IntelInstPrinter.c',
1445      'capstone/arch/X86/X86InstPrinterCommon.c',
1446      'capstone/arch/X86/X86Mapping.c',
1447      'capstone/arch/X86/X86Module.c'
1448    )
1449  endif
1450
1451  configure_file(output: 'capstone-defs.h', configuration: capstone_data)
1452
1453  capstone_cargs = [
1454    # FIXME: There does not seem to be a way to completely replace the c_args
1455    # that come from add_project_arguments() -- we can only add to them.
1456    # So: disable all warnings with a big hammer.
1457    '-Wno-error', '-w',
1458
1459    # Include all configuration defines via a header file, which will wind up
1460    # as a dependency on the object file, and thus changes here will result
1461    # in a rebuild.
1462    '-include', 'capstone-defs.h'
1463  ]
1464
1465  libcapstone = static_library('capstone',
1466                               build_by_default: false,
1467                               sources: capstone_files,
1468                               c_args: capstone_cargs,
1469                               include_directories: 'capstone/include')
1470  capstone = declare_dependency(link_with: libcapstone,
1471                                include_directories: 'capstone/include/capstone')
1472endif
1473
1474slirp = not_found
1475slirp_opt = 'disabled'
1476if have_system
1477  slirp_opt = get_option('slirp')
1478  if slirp_opt in ['enabled', 'auto', 'system']
1479    have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
1480    slirp = dependency('slirp', static: enable_static,
1481                       method: 'pkg-config',
1482                       required: slirp_opt == 'system' or
1483                                 slirp_opt == 'enabled' and not have_internal)
1484    if slirp.found()
1485      slirp_opt = 'system'
1486    elif have_internal
1487      slirp_opt = 'internal'
1488    else
1489      slirp_opt = 'disabled'
1490    endif
1491  endif
1492  if slirp_opt == 'internal'
1493    slirp_deps = []
1494    if targetos == 'windows'
1495      slirp_deps = cc.find_library('iphlpapi')
1496    endif
1497    slirp_conf = configuration_data()
1498    slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0])
1499    slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1])
1500    slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2])
1501    slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version())
1502    slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"']
1503    slirp_files = [
1504      'slirp/src/arp_table.c',
1505      'slirp/src/bootp.c',
1506      'slirp/src/cksum.c',
1507      'slirp/src/dhcpv6.c',
1508      'slirp/src/dnssearch.c',
1509      'slirp/src/if.c',
1510      'slirp/src/ip6_icmp.c',
1511      'slirp/src/ip6_input.c',
1512      'slirp/src/ip6_output.c',
1513      'slirp/src/ip_icmp.c',
1514      'slirp/src/ip_input.c',
1515      'slirp/src/ip_output.c',
1516      'slirp/src/mbuf.c',
1517      'slirp/src/misc.c',
1518      'slirp/src/ncsi.c',
1519      'slirp/src/ndp_table.c',
1520      'slirp/src/sbuf.c',
1521      'slirp/src/slirp.c',
1522      'slirp/src/socket.c',
1523      'slirp/src/state.c',
1524      'slirp/src/stream.c',
1525      'slirp/src/tcp_input.c',
1526      'slirp/src/tcp_output.c',
1527      'slirp/src/tcp_subr.c',
1528      'slirp/src/tcp_timer.c',
1529      'slirp/src/tftp.c',
1530      'slirp/src/udp.c',
1531      'slirp/src/udp6.c',
1532      'slirp/src/util.c',
1533      'slirp/src/version.c',
1534      'slirp/src/vmstate.c',
1535    ]
1536
1537    configure_file(
1538      input : 'slirp/src/libslirp-version.h.in',
1539      output : 'libslirp-version.h',
1540      configuration: slirp_conf)
1541
1542    slirp_inc = include_directories('slirp', 'slirp/src')
1543    libslirp = static_library('slirp',
1544                              build_by_default: false,
1545                              sources: slirp_files,
1546                              c_args: slirp_cargs,
1547                              include_directories: slirp_inc)
1548    slirp = declare_dependency(link_with: libslirp,
1549                               dependencies: slirp_deps,
1550                               include_directories: slirp_inc)
1551  endif
1552endif
1553
1554fdt = not_found
1555fdt_opt = get_option('fdt')
1556if have_system
1557  if fdt_opt in ['enabled', 'auto', 'system']
1558    have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
1559    fdt = cc.find_library('fdt', static: enable_static,
1560                          required: fdt_opt == 'system' or
1561                                    fdt_opt == 'enabled' and not have_internal)
1562    if fdt.found() and cc.links('''
1563       #include <libfdt.h>
1564       #include <libfdt_env.h>
1565       int main(void) { fdt_check_full(NULL, 0); return 0; }''',
1566         dependencies: fdt)
1567      fdt_opt = 'system'
1568    elif have_internal
1569      fdt_opt = 'internal'
1570    else
1571      fdt_opt = 'disabled'
1572    endif
1573  endif
1574  if fdt_opt == 'internal'
1575    fdt_files = files(
1576      'dtc/libfdt/fdt.c',
1577      'dtc/libfdt/fdt_ro.c',
1578      'dtc/libfdt/fdt_wip.c',
1579      'dtc/libfdt/fdt_sw.c',
1580      'dtc/libfdt/fdt_rw.c',
1581      'dtc/libfdt/fdt_strerror.c',
1582      'dtc/libfdt/fdt_empty_tree.c',
1583      'dtc/libfdt/fdt_addresses.c',
1584      'dtc/libfdt/fdt_overlay.c',
1585      'dtc/libfdt/fdt_check.c',
1586    )
1587
1588    fdt_inc = include_directories('dtc/libfdt')
1589    libfdt = static_library('fdt',
1590                            build_by_default: false,
1591                            sources: fdt_files,
1592                            include_directories: fdt_inc)
1593    fdt = declare_dependency(link_with: libfdt,
1594                             include_directories: fdt_inc)
1595  endif
1596endif
1597if not fdt.found() and fdt_required.length() > 0
1598  error('fdt not available but required by targets ' + ', '.join(fdt_required))
1599endif
1600
1601config_host_data.set('CONFIG_CAPSTONE', capstone.found())
1602config_host_data.set('CONFIG_FDT', fdt.found())
1603config_host_data.set('CONFIG_SLIRP', slirp.found())
1604
1605#####################
1606# Generated sources #
1607#####################
1608
1609genh += configure_file(output: 'config-host.h', configuration: config_host_data)
1610
1611hxtool = find_program('scripts/hxtool')
1612shaderinclude = find_program('scripts/shaderinclude.pl')
1613qapi_gen = find_program('scripts/qapi-gen.py')
1614qapi_gen_depends = [ meson.source_root() / 'scripts/qapi/__init__.py',
1615                     meson.source_root() / 'scripts/qapi/commands.py',
1616                     meson.source_root() / 'scripts/qapi/common.py',
1617                     meson.source_root() / 'scripts/qapi/error.py',
1618                     meson.source_root() / 'scripts/qapi/events.py',
1619                     meson.source_root() / 'scripts/qapi/expr.py',
1620                     meson.source_root() / 'scripts/qapi/gen.py',
1621                     meson.source_root() / 'scripts/qapi/introspect.py',
1622                     meson.source_root() / 'scripts/qapi/parser.py',
1623                     meson.source_root() / 'scripts/qapi/schema.py',
1624                     meson.source_root() / 'scripts/qapi/source.py',
1625                     meson.source_root() / 'scripts/qapi/types.py',
1626                     meson.source_root() / 'scripts/qapi/visit.py',
1627                     meson.source_root() / 'scripts/qapi/common.py',
1628                     meson.source_root() / 'scripts/qapi-gen.py'
1629]
1630
1631tracetool = [
1632  python, files('scripts/tracetool.py'),
1633   '--backend=' + config_host['TRACE_BACKENDS']
1634]
1635
1636qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
1637                    meson.current_source_dir(),
1638                    config_host['PKGVERSION'], meson.project_version()]
1639qemu_version = custom_target('qemu-version.h',
1640                             output: 'qemu-version.h',
1641                             command: qemu_version_cmd,
1642                             capture: true,
1643                             build_by_default: true,
1644                             build_always_stale: true)
1645genh += qemu_version
1646
1647hxdep = []
1648hx_headers = [
1649  ['qemu-options.hx', 'qemu-options.def'],
1650  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
1651]
1652if have_system
1653  hx_headers += [
1654    ['hmp-commands.hx', 'hmp-commands.h'],
1655    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
1656  ]
1657endif
1658foreach d : hx_headers
1659  hxdep += custom_target(d[1],
1660                input: files(d[0]),
1661                output: d[1],
1662                capture: true,
1663                build_by_default: true, # to be removed when added to a target
1664                command: [hxtool, '-h', '@INPUT0@'])
1665endforeach
1666genh += hxdep
1667
1668###################
1669# Collect sources #
1670###################
1671
1672authz_ss = ss.source_set()
1673blockdev_ss = ss.source_set()
1674block_ss = ss.source_set()
1675bsd_user_ss = ss.source_set()
1676chardev_ss = ss.source_set()
1677common_ss = ss.source_set()
1678crypto_ss = ss.source_set()
1679io_ss = ss.source_set()
1680linux_user_ss = ss.source_set()
1681qmp_ss = ss.source_set()
1682qom_ss = ss.source_set()
1683softmmu_ss = ss.source_set()
1684specific_fuzz_ss = ss.source_set()
1685specific_ss = ss.source_set()
1686stub_ss = ss.source_set()
1687trace_ss = ss.source_set()
1688user_ss = ss.source_set()
1689util_ss = ss.source_set()
1690
1691modules = {}
1692hw_arch = {}
1693target_arch = {}
1694target_softmmu_arch = {}
1695
1696###############
1697# Trace files #
1698###############
1699
1700# TODO: add each directory to the subdirs from its own meson.build, once
1701# we have those
1702trace_events_subdirs = [
1703  'accel/kvm',
1704  'accel/tcg',
1705  'crypto',
1706  'monitor',
1707]
1708if have_user
1709  trace_events_subdirs += [ 'linux-user' ]
1710endif
1711if have_block
1712  trace_events_subdirs += [
1713    'authz',
1714    'block',
1715    'io',
1716    'nbd',
1717    'scsi',
1718  ]
1719endif
1720if have_system
1721  trace_events_subdirs += [
1722    'audio',
1723    'backends',
1724    'backends/tpm',
1725    'chardev',
1726    'hw/9pfs',
1727    'hw/acpi',
1728    'hw/adc',
1729    'hw/alpha',
1730    'hw/arm',
1731    'hw/audio',
1732    'hw/block',
1733    'hw/block/dataplane',
1734    'hw/char',
1735    'hw/display',
1736    'hw/dma',
1737    'hw/hppa',
1738    'hw/hyperv',
1739    'hw/i2c',
1740    'hw/i386',
1741    'hw/i386/xen',
1742    'hw/ide',
1743    'hw/input',
1744    'hw/intc',
1745    'hw/isa',
1746    'hw/mem',
1747    'hw/mips',
1748    'hw/misc',
1749    'hw/misc/macio',
1750    'hw/net',
1751    'hw/net/can',
1752    'hw/nvram',
1753    'hw/pci',
1754    'hw/pci-host',
1755    'hw/ppc',
1756    'hw/rdma',
1757    'hw/rdma/vmw',
1758    'hw/rtc',
1759    'hw/s390x',
1760    'hw/scsi',
1761    'hw/sd',
1762    'hw/sparc',
1763    'hw/sparc64',
1764    'hw/ssi',
1765    'hw/timer',
1766    'hw/tpm',
1767    'hw/usb',
1768    'hw/vfio',
1769    'hw/virtio',
1770    'hw/watchdog',
1771    'hw/xen',
1772    'hw/gpio',
1773    'migration',
1774    'net',
1775    'softmmu',
1776    'ui',
1777  ]
1778endif
1779trace_events_subdirs += [
1780  'hw/core',
1781  'qapi',
1782  'qom',
1783  'target/arm',
1784  'target/hppa',
1785  'target/i386',
1786  'target/i386/kvm',
1787  'target/mips',
1788  'target/ppc',
1789  'target/riscv',
1790  'target/s390x',
1791  'target/sparc',
1792  'util',
1793]
1794
1795vhost_user = not_found
1796if 'CONFIG_VHOST_USER' in config_host
1797  libvhost_user = subproject('libvhost-user')
1798  vhost_user = libvhost_user.get_variable('vhost_user_dep')
1799endif
1800
1801subdir('qapi')
1802subdir('qobject')
1803subdir('stubs')
1804subdir('trace')
1805subdir('util')
1806subdir('qom')
1807subdir('authz')
1808subdir('crypto')
1809subdir('ui')
1810
1811
1812if enable_modules
1813  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
1814  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
1815endif
1816
1817stub_ss = stub_ss.apply(config_all, strict: false)
1818
1819util_ss.add_all(trace_ss)
1820util_ss = util_ss.apply(config_all, strict: false)
1821libqemuutil = static_library('qemuutil',
1822                             sources: util_ss.sources() + stub_ss.sources() + genh,
1823                             dependencies: [util_ss.dependencies(), m, glib, socket, malloc])
1824qemuutil = declare_dependency(link_with: libqemuutil,
1825                              sources: genh + version_res)
1826
1827decodetree = generator(find_program('scripts/decodetree.py'),
1828                       output: 'decode-@BASENAME@.c.inc',
1829                       arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
1830
1831subdir('audio')
1832subdir('io')
1833subdir('chardev')
1834subdir('fsdev')
1835subdir('libdecnumber')
1836subdir('target')
1837subdir('dump')
1838
1839block_ss.add(files(
1840  'block.c',
1841  'blockjob.c',
1842  'job.c',
1843  'qemu-io-cmds.c',
1844))
1845block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
1846
1847subdir('nbd')
1848subdir('scsi')
1849subdir('block')
1850
1851blockdev_ss.add(files(
1852  'blockdev.c',
1853  'blockdev-nbd.c',
1854  'iothread.c',
1855  'job-qmp.c',
1856), gnutls)
1857
1858# os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
1859# os-win32.c does not
1860blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
1861softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
1862
1863common_ss.add(files('cpus-common.c'))
1864
1865subdir('softmmu')
1866
1867common_ss.add(capstone)
1868specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
1869specific_ss.add(files('exec-vary.c'))
1870specific_ss.add(when: 'CONFIG_TCG', if_true: files(
1871  'fpu/softfloat.c',
1872  'tcg/optimize.c',
1873  'tcg/tcg-common.c',
1874  'tcg/tcg-op-gvec.c',
1875  'tcg/tcg-op-vec.c',
1876  'tcg/tcg-op.c',
1877  'tcg/tcg.c',
1878))
1879specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('disas/tci.c', 'tcg/tci.c'))
1880
1881subdir('backends')
1882subdir('disas')
1883subdir('migration')
1884subdir('monitor')
1885subdir('net')
1886subdir('replay')
1887subdir('hw')
1888subdir('accel')
1889subdir('plugins')
1890subdir('bsd-user')
1891subdir('linux-user')
1892
1893bsd_user_ss.add(files('gdbstub.c'))
1894specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
1895
1896linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
1897specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
1898
1899# needed for fuzzing binaries
1900subdir('tests/qtest/libqos')
1901subdir('tests/qtest/fuzz')
1902
1903########################
1904# Library dependencies #
1905########################
1906
1907block_mods = []
1908softmmu_mods = []
1909foreach d, list : modules
1910  foreach m, module_ss : list
1911    if enable_modules and targetos != 'windows'
1912      module_ss = module_ss.apply(config_all, strict: false)
1913      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
1914                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
1915      if d == 'block'
1916        block_mods += sl
1917      else
1918        softmmu_mods += sl
1919      endif
1920    else
1921      if d == 'block'
1922        block_ss.add_all(module_ss)
1923      else
1924        softmmu_ss.add_all(module_ss)
1925      endif
1926    endif
1927  endforeach
1928endforeach
1929
1930nm = find_program('nm')
1931undefsym = find_program('scripts/undefsym.py')
1932block_syms = custom_target('block.syms', output: 'block.syms',
1933                             input: [libqemuutil, block_mods],
1934                             capture: true,
1935                             command: [undefsym, nm, '@INPUT@'])
1936qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
1937                             input: [libqemuutil, softmmu_mods],
1938                             capture: true,
1939                             command: [undefsym, nm, '@INPUT@'])
1940
1941qom_ss = qom_ss.apply(config_host, strict: false)
1942libqom = static_library('qom', qom_ss.sources() + genh,
1943                        dependencies: [qom_ss.dependencies()],
1944                        name_suffix: 'fa')
1945
1946qom = declare_dependency(link_whole: libqom)
1947
1948authz_ss = authz_ss.apply(config_host, strict: false)
1949libauthz = static_library('authz', authz_ss.sources() + genh,
1950                          dependencies: [authz_ss.dependencies()],
1951                          name_suffix: 'fa',
1952                          build_by_default: false)
1953
1954authz = declare_dependency(link_whole: libauthz,
1955                           dependencies: qom)
1956
1957crypto_ss = crypto_ss.apply(config_host, strict: false)
1958libcrypto = static_library('crypto', crypto_ss.sources() + genh,
1959                           dependencies: [crypto_ss.dependencies()],
1960                           name_suffix: 'fa',
1961                           build_by_default: false)
1962
1963crypto = declare_dependency(link_whole: libcrypto,
1964                            dependencies: [authz, qom])
1965
1966io_ss = io_ss.apply(config_host, strict: false)
1967libio = static_library('io', io_ss.sources() + genh,
1968                       dependencies: [io_ss.dependencies()],
1969                       link_with: libqemuutil,
1970                       name_suffix: 'fa',
1971                       build_by_default: false)
1972
1973io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
1974
1975libmigration = static_library('migration', sources: migration_files + genh,
1976                              name_suffix: 'fa',
1977                              build_by_default: false)
1978migration = declare_dependency(link_with: libmigration,
1979                               dependencies: [zlib, qom, io])
1980softmmu_ss.add(migration)
1981
1982block_ss = block_ss.apply(config_host, strict: false)
1983libblock = static_library('block', block_ss.sources() + genh,
1984                          dependencies: block_ss.dependencies(),
1985                          link_depends: block_syms,
1986                          name_suffix: 'fa',
1987                          build_by_default: false)
1988
1989block = declare_dependency(link_whole: [libblock],
1990                           link_args: '@block.syms',
1991                           dependencies: [crypto, io])
1992
1993blockdev_ss = blockdev_ss.apply(config_host, strict: false)
1994libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
1995                             dependencies: blockdev_ss.dependencies(),
1996                             name_suffix: 'fa',
1997                             build_by_default: false)
1998
1999blockdev = declare_dependency(link_whole: [libblockdev],
2000                              dependencies: [block])
2001
2002qmp_ss = qmp_ss.apply(config_host, strict: false)
2003libqmp = static_library('qmp', qmp_ss.sources() + genh,
2004                        dependencies: qmp_ss.dependencies(),
2005                        name_suffix: 'fa',
2006                        build_by_default: false)
2007
2008qmp = declare_dependency(link_whole: [libqmp])
2009
2010libchardev = static_library('chardev', chardev_ss.sources() + genh,
2011                            name_suffix: 'fa',
2012                            dependencies: [gnutls],
2013                            build_by_default: false)
2014
2015chardev = declare_dependency(link_whole: libchardev)
2016
2017libhwcore = static_library('hwcore', sources: hwcore_files + genh,
2018                           name_suffix: 'fa',
2019                           build_by_default: false)
2020hwcore = declare_dependency(link_whole: libhwcore)
2021common_ss.add(hwcore)
2022
2023###########
2024# Targets #
2025###########
2026
2027foreach m : block_mods + softmmu_mods
2028  shared_module(m.name(),
2029                name_prefix: '',
2030                link_whole: m,
2031                install: true,
2032                install_dir: qemu_moddir)
2033endforeach
2034
2035softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
2036common_ss.add(qom, qemuutil)
2037
2038common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
2039common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
2040
2041common_all = common_ss.apply(config_all, strict: false)
2042common_all = static_library('common',
2043                            build_by_default: false,
2044                            sources: common_all.sources() + genh,
2045                            dependencies: common_all.dependencies(),
2046                            name_suffix: 'fa')
2047
2048feature_to_c = find_program('scripts/feature_to_c.sh')
2049
2050emulators = {}
2051foreach target : target_dirs
2052  config_target = config_target_mak[target]
2053  target_name = config_target['TARGET_NAME']
2054  arch = config_target['TARGET_BASE_ARCH']
2055  arch_srcs = [config_target_h[target]]
2056  arch_deps = []
2057  c_args = ['-DNEED_CPU_H',
2058            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2059            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2060  link_args = emulator_link_args
2061
2062  config_target += config_host
2063  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2064  if targetos == 'linux'
2065    target_inc += include_directories('linux-headers', is_system: true)
2066  endif
2067  if target.endswith('-softmmu')
2068    qemu_target_name = 'qemu-system-' + target_name
2069    target_type='system'
2070    t = target_softmmu_arch[arch].apply(config_target, strict: false)
2071    arch_srcs += t.sources()
2072    arch_deps += t.dependencies()
2073
2074    hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
2075    hw = hw_arch[hw_dir].apply(config_target, strict: false)
2076    arch_srcs += hw.sources()
2077    arch_deps += hw.dependencies()
2078
2079    arch_srcs += config_devices_h[target]
2080    link_args += ['@block.syms', '@qemu.syms']
2081  else
2082    abi = config_target['TARGET_ABI_DIR']
2083    target_type='user'
2084    qemu_target_name = 'qemu-' + target_name
2085    if 'CONFIG_LINUX_USER' in config_target
2086      base_dir = 'linux-user'
2087      target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
2088    else
2089      base_dir = 'bsd-user'
2090      target_inc += include_directories('bsd-user/freebsd')
2091    endif
2092    target_inc += include_directories(
2093      base_dir,
2094      base_dir / abi,
2095    )
2096    if 'CONFIG_LINUX_USER' in config_target
2097      dir = base_dir / abi
2098      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
2099      if config_target.has_key('TARGET_SYSTBL_ABI')
2100        arch_srcs += \
2101          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
2102                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
2103      endif
2104    endif
2105  endif
2106
2107  if 'TARGET_XML_FILES' in config_target
2108    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
2109                                output: target + '-gdbstub-xml.c',
2110                                input: files(config_target['TARGET_XML_FILES'].split()),
2111                                command: [feature_to_c, '@INPUT@'],
2112                                capture: true)
2113    arch_srcs += gdbstub_xml
2114  endif
2115
2116  t = target_arch[arch].apply(config_target, strict: false)
2117  arch_srcs += t.sources()
2118  arch_deps += t.dependencies()
2119
2120  target_common = common_ss.apply(config_target, strict: false)
2121  objects = common_all.extract_objects(target_common.sources())
2122  deps = target_common.dependencies()
2123
2124  target_specific = specific_ss.apply(config_target, strict: false)
2125  arch_srcs += target_specific.sources()
2126  arch_deps += target_specific.dependencies()
2127
2128  lib = static_library('qemu-' + target,
2129                 sources: arch_srcs + genh,
2130                 dependencies: arch_deps,
2131                 objects: objects,
2132                 include_directories: target_inc,
2133                 c_args: c_args,
2134                 build_by_default: false,
2135                 name_suffix: 'fa')
2136
2137  if target.endswith('-softmmu')
2138    execs = [{
2139      'name': 'qemu-system-' + target_name,
2140      'gui': false,
2141      'sources': files('softmmu/main.c'),
2142      'dependencies': []
2143    }]
2144    if targetos == 'windows' and (sdl.found() or gtk.found())
2145      execs += [{
2146        'name': 'qemu-system-' + target_name + 'w',
2147        'gui': true,
2148        'sources': files('softmmu/main.c'),
2149        'dependencies': []
2150      }]
2151    endif
2152    if config_host.has_key('CONFIG_FUZZ')
2153      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
2154      execs += [{
2155        'name': 'qemu-fuzz-' + target_name,
2156        'gui': false,
2157        'sources': specific_fuzz.sources(),
2158        'dependencies': specific_fuzz.dependencies(),
2159      }]
2160    endif
2161  else
2162    execs = [{
2163      'name': 'qemu-' + target_name,
2164      'gui': false,
2165      'sources': [],
2166      'dependencies': []
2167    }]
2168  endif
2169  foreach exe: execs
2170    exe_name = exe['name']
2171    exe_sign = 'CONFIG_HVF' in config_target
2172    if exe_sign
2173      exe_name += '-unsigned'
2174    endif
2175
2176    emulator = executable(exe_name, exe['sources'],
2177               install: not exe_sign,
2178               c_args: c_args,
2179               dependencies: arch_deps + deps + exe['dependencies'],
2180               objects: lib.extract_all_objects(recursive: true),
2181               link_language: link_language,
2182               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
2183               link_args: link_args,
2184               gui_app: exe['gui'])
2185
2186    if exe_sign
2187      emulators += {exe['name'] : custom_target(exe['name'],
2188                   install: true,
2189                   install_dir: get_option('bindir'),
2190                   depends: emulator,
2191                   output: exe['name'],
2192                   command: [
2193                     meson.current_source_dir() / 'scripts/entitlement.sh',
2194                     meson.current_build_dir() / exe_name,
2195                     meson.current_build_dir() / exe['name'],
2196                     meson.current_source_dir() / 'accel/hvf/entitlements.plist'
2197                   ])
2198      }
2199    else
2200      emulators += {exe['name']: emulator}
2201    endif
2202
2203    if 'CONFIG_TRACE_SYSTEMTAP' in config_host
2204      foreach stp: [
2205        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
2206        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
2207        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
2208        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
2209      ]
2210        custom_target(exe['name'] + stp['ext'],
2211                      input: trace_events_all,
2212                      output: exe['name'] + stp['ext'],
2213                      install: stp['install'],
2214                      install_dir: get_option('datadir') / 'systemtap/tapset',
2215                      command: [
2216                        tracetool, '--group=all', '--format=' + stp['fmt'],
2217                        '--binary=' + stp['bin'],
2218                        '--target-name=' + target_name,
2219                        '--target-type=' + target_type,
2220                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
2221                        '@INPUT@', '@OUTPUT@'
2222                      ])
2223      endforeach
2224    endif
2225  endforeach
2226endforeach
2227
2228# Other build targets
2229
2230if 'CONFIG_PLUGIN' in config_host
2231  install_headers('include/qemu/qemu-plugin.h')
2232endif
2233
2234if 'CONFIG_GUEST_AGENT' in config_host
2235  subdir('qga')
2236elif get_option('guest_agent_msi').enabled()
2237  error('Guest agent MSI requested, but the guest agent is not being built')
2238endif
2239
2240# Don't build qemu-keymap if xkbcommon is not explicitly enabled
2241# when we don't build tools or system
2242if xkbcommon.found()
2243  # used for the update-keymaps target, so include rules even if !have_tools
2244  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
2245                           dependencies: [qemuutil, xkbcommon], install: have_tools)
2246endif
2247
2248if have_tools
2249  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
2250             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
2251  qemu_io = executable('qemu-io', files('qemu-io.c'),
2252             dependencies: [block, qemuutil], install: true)
2253  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
2254               dependencies: [blockdev, qemuutil, gnutls], install: true)
2255
2256  subdir('storage-daemon')
2257  subdir('contrib/rdmacm-mux')
2258  subdir('contrib/elf2dmp')
2259
2260  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
2261             dependencies: qemuutil,
2262             install: true)
2263
2264  if 'CONFIG_VHOST_USER' in config_host
2265    subdir('contrib/vhost-user-blk')
2266    subdir('contrib/vhost-user-gpu')
2267    subdir('contrib/vhost-user-input')
2268    subdir('contrib/vhost-user-scsi')
2269  endif
2270
2271  if targetos == 'linux'
2272    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
2273               dependencies: [qemuutil, libcap_ng],
2274               install: true,
2275               install_dir: get_option('libexecdir'))
2276
2277    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
2278               dependencies: [authz, crypto, io, qom, qemuutil,
2279                              libcap_ng, mpathpersist],
2280               install: true)
2281  endif
2282
2283  if 'CONFIG_IVSHMEM' in config_host
2284    subdir('contrib/ivshmem-client')
2285    subdir('contrib/ivshmem-server')
2286  endif
2287endif
2288
2289subdir('scripts')
2290subdir('tools')
2291subdir('pc-bios')
2292subdir('docs')
2293subdir('tests')
2294if gtk.found()
2295  subdir('po')
2296endif
2297
2298if host_machine.system() == 'windows'
2299  nsis_cmd = [
2300    find_program('scripts/nsis.py'),
2301    '@OUTPUT@',
2302    get_option('prefix'),
2303    meson.current_source_dir(),
2304    host_machine.cpu(),
2305    '--',
2306    '-DDISPLAYVERSION=' + meson.project_version(),
2307  ]
2308  if build_docs
2309    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
2310  endif
2311  if gtk.found()
2312    nsis_cmd += '-DCONFIG_GTK=y'
2313  endif
2314
2315  nsis = custom_target('nsis',
2316                       output: 'qemu-setup-' + meson.project_version() + '.exe',
2317                       input: files('qemu.nsi'),
2318                       build_always_stale: true,
2319                       command: nsis_cmd + ['@INPUT@'])
2320  alias_target('installer', nsis)
2321endif
2322
2323#########################
2324# Configuration summary #
2325#########################
2326
2327# Directories
2328summary_info = {}
2329summary_info += {'Install prefix':    get_option('prefix')}
2330summary_info += {'BIOS directory':    qemu_datadir}
2331summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
2332summary_info += {'binary directory':  get_option('bindir')}
2333summary_info += {'library directory': get_option('libdir')}
2334summary_info += {'module directory':  qemu_moddir}
2335summary_info += {'libexec directory': get_option('libexecdir')}
2336summary_info += {'include directory': get_option('includedir')}
2337summary_info += {'config directory':  get_option('sysconfdir')}
2338if targetos != 'windows'
2339  summary_info += {'local state directory': get_option('localstatedir')}
2340  summary_info += {'Manual directory':      get_option('mandir')}
2341else
2342  summary_info += {'local state directory': 'queried at runtime'}
2343endif
2344summary_info += {'Doc directory':     get_option('docdir')}
2345summary_info += {'Build directory':   meson.current_build_dir()}
2346summary_info += {'Source path':       meson.current_source_dir()}
2347summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
2348summary(summary_info, bool_yn: true, section: 'Directories')
2349
2350# Host binaries
2351summary_info = {}
2352summary_info += {'git':               config_host['GIT']}
2353summary_info += {'make':              config_host['MAKE']}
2354summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
2355summary_info += {'sphinx-build':      sphinx_build.found()}
2356if config_host.has_key('HAVE_GDB_BIN')
2357  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
2358endif
2359summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
2360if targetos == 'windows' and config_host.has_key('CONFIG_GUEST_AGENT')
2361  summary_info += {'wixl':            wixl.found() ? wixl.full_path() : false}
2362endif
2363if slirp_opt != 'disabled'
2364  summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
2365endif
2366summary(summary_info, bool_yn: true, section: 'Host binaries')
2367
2368# Configurable features
2369summary_info = {}
2370summary_info += {'Documentation':     build_docs}
2371summary_info += {'system-mode emulation': have_system}
2372summary_info += {'user-mode emulation': have_user}
2373summary_info += {'block layer':       have_block}
2374summary_info += {'Install blobs':     get_option('install_blobs')}
2375summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
2376if config_host.has_key('CONFIG_MODULES')
2377  summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
2378endif
2379summary_info += {'plugin support':    config_host.has_key('CONFIG_PLUGIN')}
2380summary_info += {'fuzzing support':   config_host.has_key('CONFIG_FUZZ')}
2381if have_system
2382  summary_info += {'Audio drivers':     config_host['CONFIG_AUDIO_DRIVERS']}
2383endif
2384summary_info += {'Trace backends':    config_host['TRACE_BACKENDS']}
2385if config_host['TRACE_BACKENDS'].split().contains('simple')
2386  summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-<pid>'}
2387endif
2388summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
2389summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
2390summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
2391summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
2392summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
2393summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
2394summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
2395summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
2396summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
2397summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
2398summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
2399summary(summary_info, bool_yn: true, section: 'Configurable features')
2400
2401# Compilation information
2402summary_info = {}
2403summary_info += {'host CPU':          cpu}
2404summary_info += {'host endianness':   build_machine.endian()}
2405summary_info += {'C compiler':        meson.get_compiler('c').cmd_array()[0]}
2406summary_info += {'Host C compiler':   meson.get_compiler('c', native: true).cmd_array()[0]}
2407if link_language == 'cpp'
2408  summary_info += {'C++ compiler':      meson.get_compiler('cpp').cmd_array()[0]}
2409else
2410  summary_info += {'C++ compiler':      false}
2411endif
2412if targetos == 'darwin'
2413  summary_info += {'Objective-C compiler': meson.get_compiler('objc').cmd_array()[0]}
2414endif
2415if targetos == 'windows'
2416  if 'WIN_SDK' in config_host
2417    summary_info += {'Windows SDK':   config_host['WIN_SDK']}
2418  endif
2419endif
2420summary_info += {'ARFLAGS':           config_host['ARFLAGS']}
2421summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
2422                                               + ['-O' + get_option('optimization')]
2423                                               + (get_option('debug') ? ['-g'] : []))}
2424if link_language == 'cpp'
2425  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
2426                                               + ['-O' + get_option('optimization')]
2427                                               + (get_option('debug') ? ['-g'] : []))}
2428endif
2429link_args = get_option(link_language + '_link_args')
2430if link_args.length() > 0
2431  summary_info += {'LDFLAGS':         ' '.join(link_args)}
2432endif
2433summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
2434summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
2435summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
2436summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
2437summary_info += {'PIE':               get_option('b_pie')}
2438summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
2439summary_info += {'malloc trim support': has_malloc_trim}
2440summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
2441summary_info += {'preadv support':    config_host_data.get('CONFIG_PREADV')}
2442summary_info += {'fdatasync':         config_host.has_key('CONFIG_FDATASYNC')}
2443summary_info += {'madvise':           config_host.has_key('CONFIG_MADVISE')}
2444summary_info += {'posix_madvise':     config_host.has_key('CONFIG_POSIX_MADVISE')}
2445summary_info += {'posix_memalign':    config_host.has_key('CONFIG_POSIX_MEMALIGN')}
2446summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
2447summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
2448summary_info += {'memory allocator':  get_option('malloc')}
2449summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
2450summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
2451summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
2452summary_info += {'gcov':              get_option('b_coverage')}
2453summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
2454summary_info += {'CFI support':       get_option('cfi')}
2455if get_option('cfi')
2456  summary_info += {'CFI debug support': get_option('cfi_debug')}
2457endif
2458summary_info += {'strip binaries':    get_option('strip')}
2459summary_info += {'sparse':            sparse.found() ? sparse.full_path() : false}
2460summary_info += {'mingw32 support':   targetos == 'windows'}
2461summary(summary_info, bool_yn: true, section: 'Compilation')
2462
2463# Targets and accelerators
2464summary_info = {}
2465if have_system
2466  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
2467  summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
2468  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
2469  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
2470  summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
2471  if config_host.has_key('CONFIG_XEN_BACKEND')
2472    summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
2473  endif
2474endif
2475summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
2476if config_all.has_key('CONFIG_TCG')
2477  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
2478  summary_info += {'TCG interpreter':   tcg_arch == 'tci'}
2479endif
2480summary_info += {'target list':       ' '.join(target_dirs)}
2481if have_system
2482  summary_info += {'default devices':   get_option('default_devices')}
2483endif
2484summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
2485
2486# Block layer
2487summary_info = {}
2488summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
2489summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
2490if have_block
2491  summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
2492  summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
2493  summary_info += {'VirtFS support':    have_virtfs}
2494  summary_info += {'build virtiofs daemon': have_virtiofsd}
2495  summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
2496  summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
2497  summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
2498  summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
2499  summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
2500  summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
2501  summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
2502  summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
2503  summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
2504  summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
2505  summary_info += {'sheepdog support':  config_host.has_key('CONFIG_SHEEPDOG')}
2506  summary_info += {'FUSE exports':      fuse.found()}
2507endif
2508summary(summary_info, bool_yn: true, section: 'Block layer support')
2509
2510# Crypto
2511summary_info = {}
2512summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
2513summary_info += {'GNUTLS support':    config_host.has_key('CONFIG_GNUTLS')}
2514# TODO: add back version
2515summary_info += {'libgcrypt':         config_host.has_key('CONFIG_GCRYPT')}
2516if config_host.has_key('CONFIG_GCRYPT')
2517   summary_info += {'  hmac':            config_host.has_key('CONFIG_GCRYPT_HMAC')}
2518   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2519endif
2520# TODO: add back version
2521summary_info += {'nettle':            config_host.has_key('CONFIG_NETTLE')}
2522if config_host.has_key('CONFIG_NETTLE')
2523   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2524endif
2525summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
2526summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
2527summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
2528summary(summary_info, bool_yn: true, section: 'Crypto')
2529
2530# Libraries
2531summary_info = {}
2532if targetos == 'darwin'
2533  summary_info += {'Cocoa support':   cocoa.found()}
2534endif
2535# TODO: add back version
2536summary_info += {'SDL support':       sdl.found()}
2537summary_info += {'SDL image support': sdl_image.found()}
2538# TODO: add back version
2539summary_info += {'GTK support':       gtk.found()}
2540summary_info += {'pixman':            pixman.found()}
2541# TODO: add back version
2542summary_info += {'VTE support':       config_host.has_key('CONFIG_VTE')}
2543# TODO: add back version
2544summary_info += {'slirp support':     slirp_opt == 'disabled' ? false : slirp_opt}
2545summary_info += {'libtasn1':          config_host.has_key('CONFIG_TASN1')}
2546summary_info += {'PAM':               config_host.has_key('CONFIG_AUTH_PAM')}
2547summary_info += {'iconv support':     iconv.found()}
2548summary_info += {'curses support':    curses.found()}
2549# TODO: add back version
2550summary_info += {'virgl support':     config_host.has_key('CONFIG_VIRGL')}
2551summary_info += {'curl support':      curl.found()}
2552summary_info += {'Multipath support': mpathpersist.found()}
2553summary_info += {'VNC support':       vnc.found()}
2554if vnc.found()
2555  summary_info += {'VNC SASL support':  sasl.found()}
2556  summary_info += {'VNC JPEG support':  jpeg.found()}
2557  summary_info += {'VNC PNG support':   png.found()}
2558endif
2559summary_info += {'brlapi support':    brlapi.found()}
2560summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
2561summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
2562summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
2563summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')}
2564summary_info += {'ATTR/XATTR support': libattr.found()}
2565summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
2566summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
2567summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
2568summary_info += {'libcap-ng support': libcap_ng.found()}
2569# TODO: add back protocol and server version
2570summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
2571summary_info += {'rbd support':       rbd.found()}
2572summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
2573summary_info += {'smartcard support': config_host.has_key('CONFIG_SMARTCARD')}
2574summary_info += {'U2F support':       u2f.found()}
2575summary_info += {'libusb':            config_host.has_key('CONFIG_USB_LIBUSB')}
2576summary_info += {'usb net redir':     config_host.has_key('CONFIG_USB_REDIR')}
2577summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
2578summary_info += {'OpenGL dmabufs':    config_host.has_key('CONFIG_OPENGL_DMABUF')}
2579summary_info += {'libiscsi support':  libiscsi.found()}
2580summary_info += {'libnfs support':    libnfs.found()}
2581if targetos == 'windows'
2582  if config_host.has_key('CONFIG_GUEST_AGENT')
2583    summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
2584    summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
2585  endif
2586endif
2587summary_info += {'seccomp support':   seccomp.found()}
2588summary_info += {'GlusterFS support': glusterfs.found()}
2589summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
2590summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
2591summary_info += {'lzo support':       lzo.found()}
2592summary_info += {'snappy support':    snappy.found()}
2593summary_info += {'bzip2 support':     libbzip2.found()}
2594summary_info += {'lzfse support':     liblzfse.found()}
2595summary_info += {'zstd support':      zstd.found()}
2596summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
2597summary_info += {'libxml2':           config_host.has_key('CONFIG_LIBXML2')}
2598summary_info += {'capstone':          capstone_opt == 'disabled' ? false : capstone_opt}
2599summary_info += {'libpmem support':   config_host.has_key('CONFIG_LIBPMEM')}
2600summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')}
2601summary_info += {'libudev':           libudev.found()}
2602summary_info += {'FUSE lseek':        fuse_lseek.found()}
2603summary(summary_info, bool_yn: true, section: 'Dependencies')
2604
2605if not supported_cpus.contains(cpu)
2606  message()
2607  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
2608  message()
2609  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
2610  message('The QEMU project intends to remove support for this host CPU in')
2611  message('a future release if nobody volunteers to maintain it and to')
2612  message('provide a build host for our continuous integration setup.')
2613  message('configure has succeeded and you can continue to build, but')
2614  message('if you care about QEMU on this platform you should contact')
2615  message('us upstream at qemu-devel@nongnu.org.')
2616endif
2617
2618if not supported_oses.contains(targetos)
2619  message()
2620  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
2621  message()
2622  message('Host OS ' + targetos + 'support is not currently maintained.')
2623  message('The QEMU project intends to remove support for this host OS in')
2624  message('a future release if nobody volunteers to maintain it and to')
2625  message('provide a build host for our continuous integration setup.')
2626  message('configure has succeeded and you can continue to build, but')
2627  message('if you care about QEMU on this platform you should contact')
2628  message('us upstream at qemu-devel@nongnu.org.')
2629endif
2630