xref: /openbmc/qemu/meson.build (revision 64c9a921)
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]
1635tracetool_depends = files(
1636  'scripts/tracetool/backend/log.py',
1637  'scripts/tracetool/backend/__init__.py',
1638  'scripts/tracetool/backend/dtrace.py',
1639  'scripts/tracetool/backend/ftrace.py',
1640  'scripts/tracetool/backend/simple.py',
1641  'scripts/tracetool/backend/syslog.py',
1642  'scripts/tracetool/backend/ust.py',
1643  'scripts/tracetool/format/tcg_h.py',
1644  'scripts/tracetool/format/ust_events_c.py',
1645  'scripts/tracetool/format/ust_events_h.py',
1646  'scripts/tracetool/format/__init__.py',
1647  'scripts/tracetool/format/d.py',
1648  'scripts/tracetool/format/tcg_helper_c.py',
1649  'scripts/tracetool/format/simpletrace_stap.py',
1650  'scripts/tracetool/format/c.py',
1651  'scripts/tracetool/format/h.py',
1652  'scripts/tracetool/format/tcg_helper_h.py',
1653  'scripts/tracetool/format/log_stap.py',
1654  'scripts/tracetool/format/stap.py',
1655  'scripts/tracetool/format/tcg_helper_wrapper_h.py',
1656  'scripts/tracetool/__init__.py',
1657  'scripts/tracetool/transform.py',
1658  'scripts/tracetool/vcpu.py'
1659)
1660
1661qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
1662                    meson.current_source_dir(),
1663                    config_host['PKGVERSION'], meson.project_version()]
1664qemu_version = custom_target('qemu-version.h',
1665                             output: 'qemu-version.h',
1666                             command: qemu_version_cmd,
1667                             capture: true,
1668                             build_by_default: true,
1669                             build_always_stale: true)
1670genh += qemu_version
1671
1672hxdep = []
1673hx_headers = [
1674  ['qemu-options.hx', 'qemu-options.def'],
1675  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
1676]
1677if have_system
1678  hx_headers += [
1679    ['hmp-commands.hx', 'hmp-commands.h'],
1680    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
1681  ]
1682endif
1683foreach d : hx_headers
1684  hxdep += custom_target(d[1],
1685                input: files(d[0]),
1686                output: d[1],
1687                capture: true,
1688                build_by_default: true, # to be removed when added to a target
1689                command: [hxtool, '-h', '@INPUT0@'])
1690endforeach
1691genh += hxdep
1692
1693###################
1694# Collect sources #
1695###################
1696
1697authz_ss = ss.source_set()
1698blockdev_ss = ss.source_set()
1699block_ss = ss.source_set()
1700bsd_user_ss = ss.source_set()
1701chardev_ss = ss.source_set()
1702common_ss = ss.source_set()
1703crypto_ss = ss.source_set()
1704io_ss = ss.source_set()
1705linux_user_ss = ss.source_set()
1706qmp_ss = ss.source_set()
1707qom_ss = ss.source_set()
1708softmmu_ss = ss.source_set()
1709specific_fuzz_ss = ss.source_set()
1710specific_ss = ss.source_set()
1711stub_ss = ss.source_set()
1712trace_ss = ss.source_set()
1713user_ss = ss.source_set()
1714util_ss = ss.source_set()
1715
1716modules = {}
1717hw_arch = {}
1718target_arch = {}
1719target_softmmu_arch = {}
1720
1721###############
1722# Trace files #
1723###############
1724
1725# TODO: add each directory to the subdirs from its own meson.build, once
1726# we have those
1727trace_events_subdirs = [
1728  'accel/kvm',
1729  'accel/tcg',
1730  'crypto',
1731  'monitor',
1732]
1733if have_user
1734  trace_events_subdirs += [ 'linux-user' ]
1735endif
1736if have_block
1737  trace_events_subdirs += [
1738    'authz',
1739    'block',
1740    'io',
1741    'nbd',
1742    'scsi',
1743  ]
1744endif
1745if have_system
1746  trace_events_subdirs += [
1747    'audio',
1748    'backends',
1749    'backends/tpm',
1750    'chardev',
1751    'hw/9pfs',
1752    'hw/acpi',
1753    'hw/adc',
1754    'hw/alpha',
1755    'hw/arm',
1756    'hw/audio',
1757    'hw/block',
1758    'hw/block/dataplane',
1759    'hw/char',
1760    'hw/display',
1761    'hw/dma',
1762    'hw/hppa',
1763    'hw/hyperv',
1764    'hw/i2c',
1765    'hw/i386',
1766    'hw/i386/xen',
1767    'hw/ide',
1768    'hw/input',
1769    'hw/intc',
1770    'hw/isa',
1771    'hw/mem',
1772    'hw/mips',
1773    'hw/misc',
1774    'hw/misc/macio',
1775    'hw/net',
1776    'hw/net/can',
1777    'hw/nvram',
1778    'hw/pci',
1779    'hw/pci-host',
1780    'hw/ppc',
1781    'hw/rdma',
1782    'hw/rdma/vmw',
1783    'hw/rtc',
1784    'hw/s390x',
1785    'hw/scsi',
1786    'hw/sd',
1787    'hw/sparc',
1788    'hw/sparc64',
1789    'hw/ssi',
1790    'hw/timer',
1791    'hw/tpm',
1792    'hw/usb',
1793    'hw/vfio',
1794    'hw/virtio',
1795    'hw/watchdog',
1796    'hw/xen',
1797    'hw/gpio',
1798    'migration',
1799    'net',
1800    'softmmu',
1801    'ui',
1802  ]
1803endif
1804trace_events_subdirs += [
1805  'hw/core',
1806  'qapi',
1807  'qom',
1808  'target/arm',
1809  'target/hppa',
1810  'target/i386',
1811  'target/i386/kvm',
1812  'target/mips',
1813  'target/ppc',
1814  'target/riscv',
1815  'target/s390x',
1816  'target/sparc',
1817  'util',
1818]
1819
1820vhost_user = not_found
1821if 'CONFIG_VHOST_USER' in config_host
1822  libvhost_user = subproject('libvhost-user')
1823  vhost_user = libvhost_user.get_variable('vhost_user_dep')
1824endif
1825
1826subdir('qapi')
1827subdir('qobject')
1828subdir('stubs')
1829subdir('trace')
1830subdir('util')
1831subdir('qom')
1832subdir('authz')
1833subdir('crypto')
1834subdir('ui')
1835
1836
1837if enable_modules
1838  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
1839  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
1840endif
1841
1842stub_ss = stub_ss.apply(config_all, strict: false)
1843
1844util_ss.add_all(trace_ss)
1845util_ss = util_ss.apply(config_all, strict: false)
1846libqemuutil = static_library('qemuutil',
1847                             sources: util_ss.sources() + stub_ss.sources() + genh,
1848                             dependencies: [util_ss.dependencies(), m, glib, socket, malloc])
1849qemuutil = declare_dependency(link_with: libqemuutil,
1850                              sources: genh + version_res)
1851
1852decodetree = generator(find_program('scripts/decodetree.py'),
1853                       output: 'decode-@BASENAME@.c.inc',
1854                       arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
1855
1856subdir('audio')
1857subdir('io')
1858subdir('chardev')
1859subdir('fsdev')
1860subdir('libdecnumber')
1861subdir('target')
1862subdir('dump')
1863
1864block_ss.add(files(
1865  'block.c',
1866  'blockjob.c',
1867  'job.c',
1868  'qemu-io-cmds.c',
1869))
1870block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
1871
1872subdir('nbd')
1873subdir('scsi')
1874subdir('block')
1875
1876blockdev_ss.add(files(
1877  'blockdev.c',
1878  'blockdev-nbd.c',
1879  'iothread.c',
1880  'job-qmp.c',
1881), gnutls)
1882
1883# os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
1884# os-win32.c does not
1885blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
1886softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
1887
1888common_ss.add(files('cpus-common.c'))
1889
1890subdir('softmmu')
1891
1892common_ss.add(capstone)
1893specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
1894specific_ss.add(files('exec-vary.c'))
1895specific_ss.add(when: 'CONFIG_TCG', if_true: files(
1896  'fpu/softfloat.c',
1897  'tcg/optimize.c',
1898  'tcg/tcg-common.c',
1899  'tcg/tcg-op-gvec.c',
1900  'tcg/tcg-op-vec.c',
1901  'tcg/tcg-op.c',
1902  'tcg/tcg.c',
1903))
1904specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('disas/tci.c', 'tcg/tci.c'))
1905
1906subdir('backends')
1907subdir('disas')
1908subdir('migration')
1909subdir('monitor')
1910subdir('net')
1911subdir('replay')
1912subdir('hw')
1913subdir('accel')
1914subdir('plugins')
1915subdir('bsd-user')
1916subdir('linux-user')
1917
1918bsd_user_ss.add(files('gdbstub.c'))
1919specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
1920
1921linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
1922specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
1923
1924# needed for fuzzing binaries
1925subdir('tests/qtest/libqos')
1926subdir('tests/qtest/fuzz')
1927
1928########################
1929# Library dependencies #
1930########################
1931
1932block_mods = []
1933softmmu_mods = []
1934foreach d, list : modules
1935  foreach m, module_ss : list
1936    if enable_modules and targetos != 'windows'
1937      module_ss = module_ss.apply(config_all, strict: false)
1938      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
1939                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
1940      if d == 'block'
1941        block_mods += sl
1942      else
1943        softmmu_mods += sl
1944      endif
1945    else
1946      if d == 'block'
1947        block_ss.add_all(module_ss)
1948      else
1949        softmmu_ss.add_all(module_ss)
1950      endif
1951    endif
1952  endforeach
1953endforeach
1954
1955nm = find_program('nm')
1956undefsym = find_program('scripts/undefsym.py')
1957block_syms = custom_target('block.syms', output: 'block.syms',
1958                             input: [libqemuutil, block_mods],
1959                             capture: true,
1960                             command: [undefsym, nm, '@INPUT@'])
1961qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
1962                             input: [libqemuutil, softmmu_mods],
1963                             capture: true,
1964                             command: [undefsym, nm, '@INPUT@'])
1965
1966qom_ss = qom_ss.apply(config_host, strict: false)
1967libqom = static_library('qom', qom_ss.sources() + genh,
1968                        dependencies: [qom_ss.dependencies()],
1969                        name_suffix: 'fa')
1970
1971qom = declare_dependency(link_whole: libqom)
1972
1973authz_ss = authz_ss.apply(config_host, strict: false)
1974libauthz = static_library('authz', authz_ss.sources() + genh,
1975                          dependencies: [authz_ss.dependencies()],
1976                          name_suffix: 'fa',
1977                          build_by_default: false)
1978
1979authz = declare_dependency(link_whole: libauthz,
1980                           dependencies: qom)
1981
1982crypto_ss = crypto_ss.apply(config_host, strict: false)
1983libcrypto = static_library('crypto', crypto_ss.sources() + genh,
1984                           dependencies: [crypto_ss.dependencies()],
1985                           name_suffix: 'fa',
1986                           build_by_default: false)
1987
1988crypto = declare_dependency(link_whole: libcrypto,
1989                            dependencies: [authz, qom])
1990
1991io_ss = io_ss.apply(config_host, strict: false)
1992libio = static_library('io', io_ss.sources() + genh,
1993                       dependencies: [io_ss.dependencies()],
1994                       link_with: libqemuutil,
1995                       name_suffix: 'fa',
1996                       build_by_default: false)
1997
1998io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
1999
2000libmigration = static_library('migration', sources: migration_files + genh,
2001                              name_suffix: 'fa',
2002                              build_by_default: false)
2003migration = declare_dependency(link_with: libmigration,
2004                               dependencies: [zlib, qom, io])
2005softmmu_ss.add(migration)
2006
2007block_ss = block_ss.apply(config_host, strict: false)
2008libblock = static_library('block', block_ss.sources() + genh,
2009                          dependencies: block_ss.dependencies(),
2010                          link_depends: block_syms,
2011                          name_suffix: 'fa',
2012                          build_by_default: false)
2013
2014block = declare_dependency(link_whole: [libblock],
2015                           link_args: '@block.syms',
2016                           dependencies: [crypto, io])
2017
2018blockdev_ss = blockdev_ss.apply(config_host, strict: false)
2019libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
2020                             dependencies: blockdev_ss.dependencies(),
2021                             name_suffix: 'fa',
2022                             build_by_default: false)
2023
2024blockdev = declare_dependency(link_whole: [libblockdev],
2025                              dependencies: [block])
2026
2027qmp_ss = qmp_ss.apply(config_host, strict: false)
2028libqmp = static_library('qmp', qmp_ss.sources() + genh,
2029                        dependencies: qmp_ss.dependencies(),
2030                        name_suffix: 'fa',
2031                        build_by_default: false)
2032
2033qmp = declare_dependency(link_whole: [libqmp])
2034
2035libchardev = static_library('chardev', chardev_ss.sources() + genh,
2036                            name_suffix: 'fa',
2037                            dependencies: [gnutls],
2038                            build_by_default: false)
2039
2040chardev = declare_dependency(link_whole: libchardev)
2041
2042libhwcore = static_library('hwcore', sources: hwcore_files + genh,
2043                           name_suffix: 'fa',
2044                           build_by_default: false)
2045hwcore = declare_dependency(link_whole: libhwcore)
2046common_ss.add(hwcore)
2047
2048###########
2049# Targets #
2050###########
2051
2052foreach m : block_mods + softmmu_mods
2053  shared_module(m.name(),
2054                name_prefix: '',
2055                link_whole: m,
2056                install: true,
2057                install_dir: qemu_moddir)
2058endforeach
2059
2060softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
2061common_ss.add(qom, qemuutil)
2062
2063common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
2064common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
2065
2066common_all = common_ss.apply(config_all, strict: false)
2067common_all = static_library('common',
2068                            build_by_default: false,
2069                            sources: common_all.sources() + genh,
2070                            dependencies: common_all.dependencies(),
2071                            name_suffix: 'fa')
2072
2073feature_to_c = find_program('scripts/feature_to_c.sh')
2074
2075emulators = {}
2076foreach target : target_dirs
2077  config_target = config_target_mak[target]
2078  target_name = config_target['TARGET_NAME']
2079  arch = config_target['TARGET_BASE_ARCH']
2080  arch_srcs = [config_target_h[target]]
2081  arch_deps = []
2082  c_args = ['-DNEED_CPU_H',
2083            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2084            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2085  link_args = emulator_link_args
2086
2087  config_target += config_host
2088  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2089  if targetos == 'linux'
2090    target_inc += include_directories('linux-headers', is_system: true)
2091  endif
2092  if target.endswith('-softmmu')
2093    qemu_target_name = 'qemu-system-' + target_name
2094    target_type='system'
2095    t = target_softmmu_arch[arch].apply(config_target, strict: false)
2096    arch_srcs += t.sources()
2097    arch_deps += t.dependencies()
2098
2099    hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
2100    hw = hw_arch[hw_dir].apply(config_target, strict: false)
2101    arch_srcs += hw.sources()
2102    arch_deps += hw.dependencies()
2103
2104    arch_srcs += config_devices_h[target]
2105    link_args += ['@block.syms', '@qemu.syms']
2106  else
2107    abi = config_target['TARGET_ABI_DIR']
2108    target_type='user'
2109    qemu_target_name = 'qemu-' + target_name
2110    if 'CONFIG_LINUX_USER' in config_target
2111      base_dir = 'linux-user'
2112      target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
2113    else
2114      base_dir = 'bsd-user'
2115      target_inc += include_directories('bsd-user/freebsd')
2116    endif
2117    target_inc += include_directories(
2118      base_dir,
2119      base_dir / abi,
2120    )
2121    if 'CONFIG_LINUX_USER' in config_target
2122      dir = base_dir / abi
2123      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
2124      if config_target.has_key('TARGET_SYSTBL_ABI')
2125        arch_srcs += \
2126          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
2127                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
2128      endif
2129    endif
2130  endif
2131
2132  if 'TARGET_XML_FILES' in config_target
2133    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
2134                                output: target + '-gdbstub-xml.c',
2135                                input: files(config_target['TARGET_XML_FILES'].split()),
2136                                command: [feature_to_c, '@INPUT@'],
2137                                capture: true)
2138    arch_srcs += gdbstub_xml
2139  endif
2140
2141  t = target_arch[arch].apply(config_target, strict: false)
2142  arch_srcs += t.sources()
2143  arch_deps += t.dependencies()
2144
2145  target_common = common_ss.apply(config_target, strict: false)
2146  objects = common_all.extract_objects(target_common.sources())
2147  deps = target_common.dependencies()
2148
2149  target_specific = specific_ss.apply(config_target, strict: false)
2150  arch_srcs += target_specific.sources()
2151  arch_deps += target_specific.dependencies()
2152
2153  lib = static_library('qemu-' + target,
2154                 sources: arch_srcs + genh,
2155                 dependencies: arch_deps,
2156                 objects: objects,
2157                 include_directories: target_inc,
2158                 c_args: c_args,
2159                 build_by_default: false,
2160                 name_suffix: 'fa')
2161
2162  if target.endswith('-softmmu')
2163    execs = [{
2164      'name': 'qemu-system-' + target_name,
2165      'gui': false,
2166      'sources': files('softmmu/main.c'),
2167      'dependencies': []
2168    }]
2169    if targetos == 'windows' and (sdl.found() or gtk.found())
2170      execs += [{
2171        'name': 'qemu-system-' + target_name + 'w',
2172        'gui': true,
2173        'sources': files('softmmu/main.c'),
2174        'dependencies': []
2175      }]
2176    endif
2177    if config_host.has_key('CONFIG_FUZZ')
2178      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
2179      execs += [{
2180        'name': 'qemu-fuzz-' + target_name,
2181        'gui': false,
2182        'sources': specific_fuzz.sources(),
2183        'dependencies': specific_fuzz.dependencies(),
2184      }]
2185    endif
2186  else
2187    execs = [{
2188      'name': 'qemu-' + target_name,
2189      'gui': false,
2190      'sources': [],
2191      'dependencies': []
2192    }]
2193  endif
2194  foreach exe: execs
2195    exe_name = exe['name']
2196    exe_sign = 'CONFIG_HVF' in config_target
2197    if exe_sign
2198      exe_name += '-unsigned'
2199    endif
2200
2201    emulator = executable(exe_name, exe['sources'],
2202               install: not exe_sign,
2203               c_args: c_args,
2204               dependencies: arch_deps + deps + exe['dependencies'],
2205               objects: lib.extract_all_objects(recursive: true),
2206               link_language: link_language,
2207               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
2208               link_args: link_args,
2209               gui_app: exe['gui'])
2210
2211    if exe_sign
2212      emulators += {exe['name'] : custom_target(exe['name'],
2213                   install: true,
2214                   install_dir: get_option('bindir'),
2215                   depends: emulator,
2216                   output: exe['name'],
2217                   command: [
2218                     meson.current_source_dir() / 'scripts/entitlement.sh',
2219                     meson.current_build_dir() / exe_name,
2220                     meson.current_build_dir() / exe['name'],
2221                     meson.current_source_dir() / 'accel/hvf/entitlements.plist'
2222                   ])
2223      }
2224    else
2225      emulators += {exe['name']: emulator}
2226    endif
2227
2228    if 'CONFIG_TRACE_SYSTEMTAP' in config_host
2229      foreach stp: [
2230        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
2231        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
2232        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
2233        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
2234      ]
2235        custom_target(exe['name'] + stp['ext'],
2236                      input: trace_events_all,
2237                      output: exe['name'] + stp['ext'],
2238                      install: stp['install'],
2239                      install_dir: get_option('datadir') / 'systemtap/tapset',
2240                      command: [
2241                        tracetool, '--group=all', '--format=' + stp['fmt'],
2242                        '--binary=' + stp['bin'],
2243                        '--target-name=' + target_name,
2244                        '--target-type=' + target_type,
2245                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
2246                        '@INPUT@', '@OUTPUT@'
2247                      ],
2248                      depend_files: tracetool_depends)
2249      endforeach
2250    endif
2251  endforeach
2252endforeach
2253
2254# Other build targets
2255
2256if 'CONFIG_PLUGIN' in config_host
2257  install_headers('include/qemu/qemu-plugin.h')
2258endif
2259
2260if 'CONFIG_GUEST_AGENT' in config_host
2261  subdir('qga')
2262elif get_option('guest_agent_msi').enabled()
2263  error('Guest agent MSI requested, but the guest agent is not being built')
2264endif
2265
2266# Don't build qemu-keymap if xkbcommon is not explicitly enabled
2267# when we don't build tools or system
2268if xkbcommon.found()
2269  # used for the update-keymaps target, so include rules even if !have_tools
2270  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
2271                           dependencies: [qemuutil, xkbcommon], install: have_tools)
2272endif
2273
2274if have_tools
2275  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
2276             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
2277  qemu_io = executable('qemu-io', files('qemu-io.c'),
2278             dependencies: [block, qemuutil], install: true)
2279  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
2280               dependencies: [blockdev, qemuutil, gnutls], install: true)
2281
2282  subdir('storage-daemon')
2283  subdir('contrib/rdmacm-mux')
2284  subdir('contrib/elf2dmp')
2285
2286  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
2287             dependencies: qemuutil,
2288             install: true)
2289
2290  if 'CONFIG_VHOST_USER' in config_host
2291    subdir('contrib/vhost-user-blk')
2292    subdir('contrib/vhost-user-gpu')
2293    subdir('contrib/vhost-user-input')
2294    subdir('contrib/vhost-user-scsi')
2295  endif
2296
2297  if targetos == 'linux'
2298    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
2299               dependencies: [qemuutil, libcap_ng],
2300               install: true,
2301               install_dir: get_option('libexecdir'))
2302
2303    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
2304               dependencies: [authz, crypto, io, qom, qemuutil,
2305                              libcap_ng, mpathpersist],
2306               install: true)
2307  endif
2308
2309  if 'CONFIG_IVSHMEM' in config_host
2310    subdir('contrib/ivshmem-client')
2311    subdir('contrib/ivshmem-server')
2312  endif
2313endif
2314
2315subdir('scripts')
2316subdir('tools')
2317subdir('pc-bios')
2318subdir('docs')
2319subdir('tests')
2320if gtk.found()
2321  subdir('po')
2322endif
2323
2324if host_machine.system() == 'windows'
2325  nsis_cmd = [
2326    find_program('scripts/nsis.py'),
2327    '@OUTPUT@',
2328    get_option('prefix'),
2329    meson.current_source_dir(),
2330    host_machine.cpu(),
2331    '--',
2332    '-DDISPLAYVERSION=' + meson.project_version(),
2333  ]
2334  if build_docs
2335    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
2336  endif
2337  if gtk.found()
2338    nsis_cmd += '-DCONFIG_GTK=y'
2339  endif
2340
2341  nsis = custom_target('nsis',
2342                       output: 'qemu-setup-' + meson.project_version() + '.exe',
2343                       input: files('qemu.nsi'),
2344                       build_always_stale: true,
2345                       command: nsis_cmd + ['@INPUT@'])
2346  alias_target('installer', nsis)
2347endif
2348
2349#########################
2350# Configuration summary #
2351#########################
2352
2353# Directories
2354summary_info = {}
2355summary_info += {'Install prefix':    get_option('prefix')}
2356summary_info += {'BIOS directory':    qemu_datadir}
2357summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
2358summary_info += {'binary directory':  get_option('bindir')}
2359summary_info += {'library directory': get_option('libdir')}
2360summary_info += {'module directory':  qemu_moddir}
2361summary_info += {'libexec directory': get_option('libexecdir')}
2362summary_info += {'include directory': get_option('includedir')}
2363summary_info += {'config directory':  get_option('sysconfdir')}
2364if targetos != 'windows'
2365  summary_info += {'local state directory': get_option('localstatedir')}
2366  summary_info += {'Manual directory':      get_option('mandir')}
2367else
2368  summary_info += {'local state directory': 'queried at runtime'}
2369endif
2370summary_info += {'Doc directory':     get_option('docdir')}
2371summary_info += {'Build directory':   meson.current_build_dir()}
2372summary_info += {'Source path':       meson.current_source_dir()}
2373summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
2374summary(summary_info, bool_yn: true, section: 'Directories')
2375
2376# Host binaries
2377summary_info = {}
2378summary_info += {'git':               config_host['GIT']}
2379summary_info += {'make':              config_host['MAKE']}
2380summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
2381summary_info += {'sphinx-build':      sphinx_build.found()}
2382if config_host.has_key('HAVE_GDB_BIN')
2383  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
2384endif
2385summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
2386if targetos == 'windows' and config_host.has_key('CONFIG_GUEST_AGENT')
2387  summary_info += {'wixl':            wixl.found() ? wixl.full_path() : false}
2388endif
2389if slirp_opt != 'disabled'
2390  summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
2391endif
2392summary(summary_info, bool_yn: true, section: 'Host binaries')
2393
2394# Configurable features
2395summary_info = {}
2396summary_info += {'Documentation':     build_docs}
2397summary_info += {'system-mode emulation': have_system}
2398summary_info += {'user-mode emulation': have_user}
2399summary_info += {'block layer':       have_block}
2400summary_info += {'Install blobs':     get_option('install_blobs')}
2401summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
2402if config_host.has_key('CONFIG_MODULES')
2403  summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
2404endif
2405summary_info += {'plugin support':    config_host.has_key('CONFIG_PLUGIN')}
2406summary_info += {'fuzzing support':   config_host.has_key('CONFIG_FUZZ')}
2407if have_system
2408  summary_info += {'Audio drivers':     config_host['CONFIG_AUDIO_DRIVERS']}
2409endif
2410summary_info += {'Trace backends':    config_host['TRACE_BACKENDS']}
2411if config_host['TRACE_BACKENDS'].split().contains('simple')
2412  summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-<pid>'}
2413endif
2414summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
2415summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
2416summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
2417summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
2418summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
2419summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
2420summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
2421summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
2422summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
2423summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
2424summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
2425summary(summary_info, bool_yn: true, section: 'Configurable features')
2426
2427# Compilation information
2428summary_info = {}
2429summary_info += {'host CPU':          cpu}
2430summary_info += {'host endianness':   build_machine.endian()}
2431summary_info += {'C compiler':        meson.get_compiler('c').cmd_array()[0]}
2432summary_info += {'Host C compiler':   meson.get_compiler('c', native: true).cmd_array()[0]}
2433if link_language == 'cpp'
2434  summary_info += {'C++ compiler':      meson.get_compiler('cpp').cmd_array()[0]}
2435else
2436  summary_info += {'C++ compiler':      false}
2437endif
2438if targetos == 'darwin'
2439  summary_info += {'Objective-C compiler': meson.get_compiler('objc').cmd_array()[0]}
2440endif
2441if targetos == 'windows'
2442  if 'WIN_SDK' in config_host
2443    summary_info += {'Windows SDK':   config_host['WIN_SDK']}
2444  endif
2445endif
2446summary_info += {'ARFLAGS':           config_host['ARFLAGS']}
2447summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
2448                                               + ['-O' + get_option('optimization')]
2449                                               + (get_option('debug') ? ['-g'] : []))}
2450if link_language == 'cpp'
2451  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
2452                                               + ['-O' + get_option('optimization')]
2453                                               + (get_option('debug') ? ['-g'] : []))}
2454endif
2455link_args = get_option(link_language + '_link_args')
2456if link_args.length() > 0
2457  summary_info += {'LDFLAGS':         ' '.join(link_args)}
2458endif
2459summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
2460summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
2461summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
2462summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
2463summary_info += {'PIE':               get_option('b_pie')}
2464summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
2465summary_info += {'malloc trim support': has_malloc_trim}
2466summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
2467summary_info += {'preadv support':    config_host_data.get('CONFIG_PREADV')}
2468summary_info += {'fdatasync':         config_host.has_key('CONFIG_FDATASYNC')}
2469summary_info += {'madvise':           config_host.has_key('CONFIG_MADVISE')}
2470summary_info += {'posix_madvise':     config_host.has_key('CONFIG_POSIX_MADVISE')}
2471summary_info += {'posix_memalign':    config_host.has_key('CONFIG_POSIX_MEMALIGN')}
2472summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
2473summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
2474summary_info += {'memory allocator':  get_option('malloc')}
2475summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
2476summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
2477summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
2478summary_info += {'gcov':              get_option('b_coverage')}
2479summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
2480summary_info += {'CFI support':       get_option('cfi')}
2481if get_option('cfi')
2482  summary_info += {'CFI debug support': get_option('cfi_debug')}
2483endif
2484summary_info += {'strip binaries':    get_option('strip')}
2485summary_info += {'sparse':            sparse.found() ? sparse.full_path() : false}
2486summary_info += {'mingw32 support':   targetos == 'windows'}
2487summary(summary_info, bool_yn: true, section: 'Compilation')
2488
2489# Targets and accelerators
2490summary_info = {}
2491if have_system
2492  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
2493  summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
2494  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
2495  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
2496  summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
2497  if config_host.has_key('CONFIG_XEN_BACKEND')
2498    summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
2499  endif
2500endif
2501summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
2502if config_all.has_key('CONFIG_TCG')
2503  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
2504  summary_info += {'TCG interpreter':   tcg_arch == 'tci'}
2505endif
2506summary_info += {'target list':       ' '.join(target_dirs)}
2507if have_system
2508  summary_info += {'default devices':   get_option('default_devices')}
2509endif
2510summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
2511
2512# Block layer
2513summary_info = {}
2514summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
2515summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
2516if have_block
2517  summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
2518  summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
2519  summary_info += {'VirtFS support':    have_virtfs}
2520  summary_info += {'build virtiofs daemon': have_virtiofsd}
2521  summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
2522  summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
2523  summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
2524  summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
2525  summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
2526  summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
2527  summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
2528  summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
2529  summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
2530  summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
2531  summary_info += {'sheepdog support':  config_host.has_key('CONFIG_SHEEPDOG')}
2532  summary_info += {'FUSE exports':      fuse.found()}
2533endif
2534summary(summary_info, bool_yn: true, section: 'Block layer support')
2535
2536# Crypto
2537summary_info = {}
2538summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
2539summary_info += {'GNUTLS support':    config_host.has_key('CONFIG_GNUTLS')}
2540# TODO: add back version
2541summary_info += {'libgcrypt':         config_host.has_key('CONFIG_GCRYPT')}
2542if config_host.has_key('CONFIG_GCRYPT')
2543   summary_info += {'  hmac':            config_host.has_key('CONFIG_GCRYPT_HMAC')}
2544   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2545endif
2546# TODO: add back version
2547summary_info += {'nettle':            config_host.has_key('CONFIG_NETTLE')}
2548if config_host.has_key('CONFIG_NETTLE')
2549   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2550endif
2551summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
2552summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
2553summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
2554summary(summary_info, bool_yn: true, section: 'Crypto')
2555
2556# Libraries
2557summary_info = {}
2558if targetos == 'darwin'
2559  summary_info += {'Cocoa support':   cocoa.found()}
2560endif
2561# TODO: add back version
2562summary_info += {'SDL support':       sdl.found()}
2563summary_info += {'SDL image support': sdl_image.found()}
2564# TODO: add back version
2565summary_info += {'GTK support':       gtk.found()}
2566summary_info += {'pixman':            pixman.found()}
2567# TODO: add back version
2568summary_info += {'VTE support':       config_host.has_key('CONFIG_VTE')}
2569# TODO: add back version
2570summary_info += {'slirp support':     slirp_opt == 'disabled' ? false : slirp_opt}
2571summary_info += {'libtasn1':          config_host.has_key('CONFIG_TASN1')}
2572summary_info += {'PAM':               config_host.has_key('CONFIG_AUTH_PAM')}
2573summary_info += {'iconv support':     iconv.found()}
2574summary_info += {'curses support':    curses.found()}
2575# TODO: add back version
2576summary_info += {'virgl support':     config_host.has_key('CONFIG_VIRGL')}
2577summary_info += {'curl support':      curl.found()}
2578summary_info += {'Multipath support': mpathpersist.found()}
2579summary_info += {'VNC support':       vnc.found()}
2580if vnc.found()
2581  summary_info += {'VNC SASL support':  sasl.found()}
2582  summary_info += {'VNC JPEG support':  jpeg.found()}
2583  summary_info += {'VNC PNG support':   png.found()}
2584endif
2585summary_info += {'brlapi support':    brlapi.found()}
2586summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
2587summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
2588summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
2589summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')}
2590summary_info += {'ATTR/XATTR support': libattr.found()}
2591summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
2592summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
2593summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
2594summary_info += {'libcap-ng support': libcap_ng.found()}
2595# TODO: add back protocol and server version
2596summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
2597summary_info += {'rbd support':       rbd.found()}
2598summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
2599summary_info += {'smartcard support': config_host.has_key('CONFIG_SMARTCARD')}
2600summary_info += {'U2F support':       u2f.found()}
2601summary_info += {'libusb':            config_host.has_key('CONFIG_USB_LIBUSB')}
2602summary_info += {'usb net redir':     config_host.has_key('CONFIG_USB_REDIR')}
2603summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
2604summary_info += {'OpenGL dmabufs':    config_host.has_key('CONFIG_OPENGL_DMABUF')}
2605summary_info += {'libiscsi support':  libiscsi.found()}
2606summary_info += {'libnfs support':    libnfs.found()}
2607if targetos == 'windows'
2608  if config_host.has_key('CONFIG_GUEST_AGENT')
2609    summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
2610    summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
2611  endif
2612endif
2613summary_info += {'seccomp support':   seccomp.found()}
2614summary_info += {'GlusterFS support': glusterfs.found()}
2615summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
2616summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
2617summary_info += {'lzo support':       lzo.found()}
2618summary_info += {'snappy support':    snappy.found()}
2619summary_info += {'bzip2 support':     libbzip2.found()}
2620summary_info += {'lzfse support':     liblzfse.found()}
2621summary_info += {'zstd support':      zstd.found()}
2622summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
2623summary_info += {'libxml2':           config_host.has_key('CONFIG_LIBXML2')}
2624summary_info += {'capstone':          capstone_opt == 'disabled' ? false : capstone_opt}
2625summary_info += {'libpmem support':   config_host.has_key('CONFIG_LIBPMEM')}
2626summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')}
2627summary_info += {'libudev':           libudev.found()}
2628summary_info += {'FUSE lseek':        fuse_lseek.found()}
2629summary(summary_info, bool_yn: true, section: 'Dependencies')
2630
2631if not supported_cpus.contains(cpu)
2632  message()
2633  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
2634  message()
2635  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
2636  message('The QEMU project intends to remove support for this host CPU in')
2637  message('a future release if nobody volunteers to maintain it and to')
2638  message('provide a build host for our continuous integration setup.')
2639  message('configure has succeeded and you can continue to build, but')
2640  message('if you care about QEMU on this platform you should contact')
2641  message('us upstream at qemu-devel@nongnu.org.')
2642endif
2643
2644if not supported_oses.contains(targetos)
2645  message()
2646  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
2647  message()
2648  message('Host OS ' + targetos + 'support is not currently maintained.')
2649  message('The QEMU project intends to remove support for this host OS in')
2650  message('a future release if nobody volunteers to maintain it and to')
2651  message('provide a build host for our continuous integration setup.')
2652  message('configure has succeeded and you can continue to build, but')
2653  message('if you care about QEMU on this platform you should contact')
2654  message('us upstream at qemu-devel@nongnu.org.')
2655endif
2656