xref: /qemu/meson.build (revision c9737765)
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'))
1130
1131ignored = ['CONFIG_QEMU_INTERP_PREFIX'] # actually per-target
1132arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
1133strings = ['HOST_DSOSUF', 'CONFIG_IASL']
1134foreach k, v: config_host
1135  if ignored.contains(k)
1136    # do nothing
1137  elif arrays.contains(k)
1138    if v != ''
1139      v = '"' + '", "'.join(v.split()) + '", '
1140    endif
1141    config_host_data.set(k, v)
1142  elif k == 'ARCH'
1143    config_host_data.set('HOST_' + v.to_upper(), 1)
1144  elif strings.contains(k)
1145    if not k.startswith('CONFIG_')
1146      k = 'CONFIG_' + k.to_upper()
1147    endif
1148    config_host_data.set_quoted(k, v)
1149  elif k.startswith('CONFIG_') or k.startswith('HAVE_') or k.startswith('HOST_')
1150    config_host_data.set(k, v == 'y' ? 1 : v)
1151  endif
1152endforeach
1153
1154########################
1155# Target configuration #
1156########################
1157
1158minikconf = find_program('scripts/minikconf.py')
1159config_all = {}
1160config_all_devices = {}
1161config_all_disas = {}
1162config_devices_mak_list = []
1163config_devices_h = {}
1164config_target_h = {}
1165config_target_mak = {}
1166
1167disassemblers = {
1168  'alpha' : ['CONFIG_ALPHA_DIS'],
1169  'arm' : ['CONFIG_ARM_DIS'],
1170  'avr' : ['CONFIG_AVR_DIS'],
1171  'cris' : ['CONFIG_CRIS_DIS'],
1172  'hppa' : ['CONFIG_HPPA_DIS'],
1173  'i386' : ['CONFIG_I386_DIS'],
1174  'x86_64' : ['CONFIG_I386_DIS'],
1175  'x32' : ['CONFIG_I386_DIS'],
1176  'lm32' : ['CONFIG_LM32_DIS'],
1177  'm68k' : ['CONFIG_M68K_DIS'],
1178  'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
1179  'mips' : ['CONFIG_MIPS_DIS'],
1180  'moxie' : ['CONFIG_MOXIE_DIS'],
1181  'nios2' : ['CONFIG_NIOS2_DIS'],
1182  'or1k' : ['CONFIG_OPENRISC_DIS'],
1183  'ppc' : ['CONFIG_PPC_DIS'],
1184  'riscv' : ['CONFIG_RISCV_DIS'],
1185  'rx' : ['CONFIG_RX_DIS'],
1186  's390' : ['CONFIG_S390_DIS'],
1187  'sh4' : ['CONFIG_SH4_DIS'],
1188  'sparc' : ['CONFIG_SPARC_DIS'],
1189  'xtensa' : ['CONFIG_XTENSA_DIS'],
1190}
1191if link_language == 'cpp'
1192  disassemblers += {
1193    'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
1194    'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
1195    'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
1196  }
1197endif
1198
1199host_kconfig = \
1200  ('CONFIG_TPM' in config_host ? ['CONFIG_TPM=y'] : []) + \
1201  ('CONFIG_SPICE' in config_host ? ['CONFIG_SPICE=y'] : []) + \
1202  ('CONFIG_IVSHMEM' in config_host ? ['CONFIG_IVSHMEM=y'] : []) + \
1203  ('CONFIG_OPENGL' in config_host ? ['CONFIG_OPENGL=y'] : []) + \
1204  (x11.found() ? ['CONFIG_X11=y'] : []) + \
1205  ('CONFIG_VHOST_USER' in config_host ? ['CONFIG_VHOST_USER=y'] : []) + \
1206  ('CONFIG_VHOST_VDPA' in config_host ? ['CONFIG_VHOST_VDPA=y'] : []) + \
1207  ('CONFIG_VHOST_KERNEL' in config_host ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
1208  (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
1209  ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \
1210  ('CONFIG_PVRDMA' in config_host ? ['CONFIG_PVRDMA=y'] : [])
1211
1212ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
1213
1214default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
1215actual_target_dirs = []
1216fdt_required = []
1217foreach target : target_dirs
1218  config_target = { 'TARGET_NAME': target.split('-')[0] }
1219  if target.endswith('linux-user')
1220    if targetos != 'linux'
1221      if default_targets
1222        continue
1223      endif
1224      error('Target @0@ is only available on a Linux host'.format(target))
1225    endif
1226    config_target += { 'CONFIG_LINUX_USER': 'y' }
1227  elif target.endswith('bsd-user')
1228    if 'CONFIG_BSD' not in config_host
1229      if default_targets
1230        continue
1231      endif
1232      error('Target @0@ is only available on a BSD host'.format(target))
1233    endif
1234    config_target += { 'CONFIG_BSD_USER': 'y' }
1235  elif target.endswith('softmmu')
1236    config_target += { 'CONFIG_SOFTMMU': 'y' }
1237  endif
1238  if target.endswith('-user')
1239    config_target += {
1240      'CONFIG_USER_ONLY': 'y',
1241      'CONFIG_QEMU_INTERP_PREFIX':
1242        config_host['CONFIG_QEMU_INTERP_PREFIX'].format(config_target['TARGET_NAME'])
1243    }
1244  endif
1245
1246  accel_kconfig = []
1247  foreach sym: accelerators
1248    if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
1249      config_target += { sym: 'y' }
1250      config_all += { sym: 'y' }
1251      if sym == 'CONFIG_TCG' and tcg_arch == 'tci'
1252        config_target += { 'CONFIG_TCG_INTERPRETER': 'y' }
1253      elif sym == 'CONFIG_XEN' and have_xen_pci_passthrough
1254        config_target += { 'CONFIG_XEN_PCI_PASSTHROUGH': 'y' }
1255      endif
1256      accel_kconfig += [ sym + '=y' ]
1257    endif
1258  endforeach
1259  if accel_kconfig.length() == 0
1260    if default_targets
1261      continue
1262    endif
1263    error('No accelerator available for target @0@'.format(target))
1264  endif
1265
1266  actual_target_dirs += target
1267  config_target += keyval.load('default-configs/targets' / target + '.mak')
1268  config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
1269
1270  if 'TARGET_NEED_FDT' in config_target
1271    fdt_required += target
1272  endif
1273
1274  # Add default keys
1275  if 'TARGET_BASE_ARCH' not in config_target
1276    config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
1277  endif
1278  if 'TARGET_ABI_DIR' not in config_target
1279    config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
1280  endif
1281
1282  foreach k, v: disassemblers
1283    if config_host['ARCH'].startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
1284      foreach sym: v
1285        config_target += { sym: 'y' }
1286        config_all_disas += { sym: 'y' }
1287      endforeach
1288    endif
1289  endforeach
1290
1291  config_target_data = configuration_data()
1292  foreach k, v: config_target
1293    if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
1294      # do nothing
1295    elif ignored.contains(k)
1296      # do nothing
1297    elif k == 'TARGET_BASE_ARCH'
1298      # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
1299      # not used to select files from sourcesets.
1300      config_target_data.set('TARGET_' + v.to_upper(), 1)
1301    elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
1302      config_target_data.set_quoted(k, v)
1303    elif v == 'y'
1304      config_target_data.set(k, 1)
1305    else
1306      config_target_data.set(k, v)
1307    endif
1308  endforeach
1309  config_target_h += {target: configure_file(output: target + '-config-target.h',
1310                                               configuration: config_target_data)}
1311
1312  if target.endswith('-softmmu')
1313    config_devices_mak = target + '-config-devices.mak'
1314    config_devices_mak = configure_file(
1315      input: ['default-configs/devices' / target + '.mak', 'Kconfig'],
1316      output: config_devices_mak,
1317      depfile: config_devices_mak + '.d',
1318      capture: true,
1319      command: [minikconf,
1320                get_option('default_devices') ? '--defconfig' : '--allnoconfig',
1321                config_devices_mak, '@DEPFILE@', '@INPUT@',
1322                host_kconfig, accel_kconfig])
1323
1324    config_devices_data = configuration_data()
1325    config_devices = keyval.load(config_devices_mak)
1326    foreach k, v: config_devices
1327      config_devices_data.set(k, 1)
1328    endforeach
1329    config_devices_mak_list += config_devices_mak
1330    config_devices_h += {target: configure_file(output: target + '-config-devices.h',
1331                                                configuration: config_devices_data)}
1332    config_target += config_devices
1333    config_all_devices += config_devices
1334  endif
1335  config_target_mak += {target: config_target}
1336endforeach
1337target_dirs = actual_target_dirs
1338
1339# This configuration is used to build files that are shared by
1340# multiple binaries, and then extracted out of the "common"
1341# static_library target.
1342#
1343# We do not use all_sources()/all_dependencies(), because it would
1344# build literally all source files, including devices only used by
1345# targets that are not built for this compilation.  The CONFIG_ALL
1346# pseudo symbol replaces it.
1347
1348config_all += config_all_devices
1349config_all += config_host
1350config_all += config_all_disas
1351config_all += {
1352  'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'),
1353  'CONFIG_SOFTMMU': have_system,
1354  'CONFIG_USER_ONLY': have_user,
1355  'CONFIG_ALL': true,
1356}
1357
1358##############
1359# Submodules #
1360##############
1361
1362capstone = not_found
1363capstone_opt = get_option('capstone')
1364if capstone_opt in ['enabled', 'auto', 'system']
1365  have_internal = fs.exists(meson.current_source_dir() / 'capstone/Makefile')
1366  capstone = dependency('capstone', version: '>=4.0',
1367                        static: enable_static, method: 'pkg-config',
1368                        required: capstone_opt == 'system' or
1369                                  capstone_opt == 'enabled' and not have_internal)
1370  if capstone.found()
1371    capstone_opt = 'system'
1372  elif have_internal
1373    capstone_opt = 'internal'
1374  else
1375    capstone_opt = 'disabled'
1376  endif
1377endif
1378if capstone_opt == 'internal'
1379  capstone_data = configuration_data()
1380  capstone_data.set('CAPSTONE_USE_SYS_DYN_MEM', '1')
1381
1382  capstone_files = files(
1383    'capstone/cs.c',
1384    'capstone/MCInst.c',
1385    'capstone/MCInstrDesc.c',
1386    'capstone/MCRegisterInfo.c',
1387    'capstone/SStream.c',
1388    'capstone/utils.c'
1389  )
1390
1391  if 'CONFIG_ARM_DIS' in config_all_disas
1392    capstone_data.set('CAPSTONE_HAS_ARM', '1')
1393    capstone_files += files(
1394      'capstone/arch/ARM/ARMDisassembler.c',
1395      'capstone/arch/ARM/ARMInstPrinter.c',
1396      'capstone/arch/ARM/ARMMapping.c',
1397      'capstone/arch/ARM/ARMModule.c'
1398    )
1399  endif
1400
1401  # FIXME: This config entry currently depends on a c++ compiler.
1402  # Which is needed for building libvixl, but not for capstone.
1403  if 'CONFIG_ARM_A64_DIS' in config_all_disas
1404    capstone_data.set('CAPSTONE_HAS_ARM64', '1')
1405    capstone_files += files(
1406      'capstone/arch/AArch64/AArch64BaseInfo.c',
1407      'capstone/arch/AArch64/AArch64Disassembler.c',
1408      'capstone/arch/AArch64/AArch64InstPrinter.c',
1409      'capstone/arch/AArch64/AArch64Mapping.c',
1410      'capstone/arch/AArch64/AArch64Module.c'
1411    )
1412  endif
1413
1414  if 'CONFIG_PPC_DIS' in config_all_disas
1415    capstone_data.set('CAPSTONE_HAS_POWERPC', '1')
1416    capstone_files += files(
1417      'capstone/arch/PowerPC/PPCDisassembler.c',
1418      'capstone/arch/PowerPC/PPCInstPrinter.c',
1419      'capstone/arch/PowerPC/PPCMapping.c',
1420      'capstone/arch/PowerPC/PPCModule.c'
1421    )
1422  endif
1423
1424  if 'CONFIG_S390_DIS' in config_all_disas
1425    capstone_data.set('CAPSTONE_HAS_SYSZ', '1')
1426    capstone_files += files(
1427      'capstone/arch/SystemZ/SystemZDisassembler.c',
1428      'capstone/arch/SystemZ/SystemZInstPrinter.c',
1429      'capstone/arch/SystemZ/SystemZMapping.c',
1430      'capstone/arch/SystemZ/SystemZModule.c',
1431      'capstone/arch/SystemZ/SystemZMCTargetDesc.c'
1432    )
1433  endif
1434
1435  if 'CONFIG_I386_DIS' in config_all_disas
1436    capstone_data.set('CAPSTONE_HAS_X86', 1)
1437    capstone_files += files(
1438      'capstone/arch/X86/X86Disassembler.c',
1439      'capstone/arch/X86/X86DisassemblerDecoder.c',
1440      'capstone/arch/X86/X86ATTInstPrinter.c',
1441      'capstone/arch/X86/X86IntelInstPrinter.c',
1442      'capstone/arch/X86/X86InstPrinterCommon.c',
1443      'capstone/arch/X86/X86Mapping.c',
1444      'capstone/arch/X86/X86Module.c'
1445    )
1446  endif
1447
1448  configure_file(output: 'capstone-defs.h', configuration: capstone_data)
1449
1450  capstone_cargs = [
1451    # FIXME: There does not seem to be a way to completely replace the c_args
1452    # that come from add_project_arguments() -- we can only add to them.
1453    # So: disable all warnings with a big hammer.
1454    '-Wno-error', '-w',
1455
1456    # Include all configuration defines via a header file, which will wind up
1457    # as a dependency on the object file, and thus changes here will result
1458    # in a rebuild.
1459    '-include', 'capstone-defs.h'
1460  ]
1461
1462  libcapstone = static_library('capstone',
1463                               build_by_default: false,
1464                               sources: capstone_files,
1465                               c_args: capstone_cargs,
1466                               include_directories: 'capstone/include')
1467  capstone = declare_dependency(link_with: libcapstone,
1468                                include_directories: 'capstone/include/capstone')
1469endif
1470
1471slirp = not_found
1472slirp_opt = 'disabled'
1473if have_system
1474  slirp_opt = get_option('slirp')
1475  if slirp_opt in ['enabled', 'auto', 'system']
1476    have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
1477    slirp = dependency('slirp', static: enable_static,
1478                       method: 'pkg-config',
1479                       required: slirp_opt == 'system' or
1480                                 slirp_opt == 'enabled' and not have_internal)
1481    if slirp.found()
1482      slirp_opt = 'system'
1483    elif have_internal
1484      slirp_opt = 'internal'
1485    else
1486      slirp_opt = 'disabled'
1487    endif
1488  endif
1489  if slirp_opt == 'internal'
1490    slirp_deps = []
1491    if targetos == 'windows'
1492      slirp_deps = cc.find_library('iphlpapi')
1493    endif
1494    slirp_conf = configuration_data()
1495    slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0])
1496    slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1])
1497    slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2])
1498    slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version())
1499    slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"']
1500    slirp_files = [
1501      'slirp/src/arp_table.c',
1502      'slirp/src/bootp.c',
1503      'slirp/src/cksum.c',
1504      'slirp/src/dhcpv6.c',
1505      'slirp/src/dnssearch.c',
1506      'slirp/src/if.c',
1507      'slirp/src/ip6_icmp.c',
1508      'slirp/src/ip6_input.c',
1509      'slirp/src/ip6_output.c',
1510      'slirp/src/ip_icmp.c',
1511      'slirp/src/ip_input.c',
1512      'slirp/src/ip_output.c',
1513      'slirp/src/mbuf.c',
1514      'slirp/src/misc.c',
1515      'slirp/src/ncsi.c',
1516      'slirp/src/ndp_table.c',
1517      'slirp/src/sbuf.c',
1518      'slirp/src/slirp.c',
1519      'slirp/src/socket.c',
1520      'slirp/src/state.c',
1521      'slirp/src/stream.c',
1522      'slirp/src/tcp_input.c',
1523      'slirp/src/tcp_output.c',
1524      'slirp/src/tcp_subr.c',
1525      'slirp/src/tcp_timer.c',
1526      'slirp/src/tftp.c',
1527      'slirp/src/udp.c',
1528      'slirp/src/udp6.c',
1529      'slirp/src/util.c',
1530      'slirp/src/version.c',
1531      'slirp/src/vmstate.c',
1532    ]
1533
1534    configure_file(
1535      input : 'slirp/src/libslirp-version.h.in',
1536      output : 'libslirp-version.h',
1537      configuration: slirp_conf)
1538
1539    slirp_inc = include_directories('slirp', 'slirp/src')
1540    libslirp = static_library('slirp',
1541                              build_by_default: false,
1542                              sources: slirp_files,
1543                              c_args: slirp_cargs,
1544                              include_directories: slirp_inc)
1545    slirp = declare_dependency(link_with: libslirp,
1546                               dependencies: slirp_deps,
1547                               include_directories: slirp_inc)
1548  endif
1549endif
1550
1551fdt = not_found
1552fdt_opt = get_option('fdt')
1553if have_system
1554  if fdt_opt in ['enabled', 'auto', 'system']
1555    have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
1556    fdt = cc.find_library('fdt', static: enable_static,
1557                          required: fdt_opt == 'system' or
1558                                    fdt_opt == 'enabled' and not have_internal)
1559    if fdt.found() and cc.links('''
1560       #include <libfdt.h>
1561       #include <libfdt_env.h>
1562       int main(void) { fdt_check_full(NULL, 0); return 0; }''',
1563         dependencies: fdt)
1564      fdt_opt = 'system'
1565    elif have_internal
1566      fdt_opt = 'internal'
1567    else
1568      fdt_opt = 'disabled'
1569    endif
1570  endif
1571  if fdt_opt == 'internal'
1572    fdt_files = files(
1573      'dtc/libfdt/fdt.c',
1574      'dtc/libfdt/fdt_ro.c',
1575      'dtc/libfdt/fdt_wip.c',
1576      'dtc/libfdt/fdt_sw.c',
1577      'dtc/libfdt/fdt_rw.c',
1578      'dtc/libfdt/fdt_strerror.c',
1579      'dtc/libfdt/fdt_empty_tree.c',
1580      'dtc/libfdt/fdt_addresses.c',
1581      'dtc/libfdt/fdt_overlay.c',
1582      'dtc/libfdt/fdt_check.c',
1583    )
1584
1585    fdt_inc = include_directories('dtc/libfdt')
1586    libfdt = static_library('fdt',
1587                            build_by_default: false,
1588                            sources: fdt_files,
1589                            include_directories: fdt_inc)
1590    fdt = declare_dependency(link_with: libfdt,
1591                             include_directories: fdt_inc)
1592  endif
1593endif
1594if not fdt.found() and fdt_required.length() > 0
1595  error('fdt not available but required by targets ' + ', '.join(fdt_required))
1596endif
1597
1598config_host_data.set('CONFIG_CAPSTONE', capstone.found())
1599config_host_data.set('CONFIG_FDT', fdt.found())
1600config_host_data.set('CONFIG_SLIRP', slirp.found())
1601
1602#####################
1603# Generated sources #
1604#####################
1605
1606genh += configure_file(output: 'config-host.h', configuration: config_host_data)
1607
1608hxtool = find_program('scripts/hxtool')
1609shaderinclude = find_program('scripts/shaderinclude.pl')
1610qapi_gen = find_program('scripts/qapi-gen.py')
1611qapi_gen_depends = [ meson.source_root() / 'scripts/qapi/__init__.py',
1612                     meson.source_root() / 'scripts/qapi/commands.py',
1613                     meson.source_root() / 'scripts/qapi/common.py',
1614                     meson.source_root() / 'scripts/qapi/error.py',
1615                     meson.source_root() / 'scripts/qapi/events.py',
1616                     meson.source_root() / 'scripts/qapi/expr.py',
1617                     meson.source_root() / 'scripts/qapi/gen.py',
1618                     meson.source_root() / 'scripts/qapi/introspect.py',
1619                     meson.source_root() / 'scripts/qapi/parser.py',
1620                     meson.source_root() / 'scripts/qapi/schema.py',
1621                     meson.source_root() / 'scripts/qapi/source.py',
1622                     meson.source_root() / 'scripts/qapi/types.py',
1623                     meson.source_root() / 'scripts/qapi/visit.py',
1624                     meson.source_root() / 'scripts/qapi/common.py',
1625                     meson.source_root() / 'scripts/qapi-gen.py'
1626]
1627
1628tracetool = [
1629  python, files('scripts/tracetool.py'),
1630   '--backend=' + config_host['TRACE_BACKENDS']
1631]
1632
1633qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
1634                    meson.current_source_dir(),
1635                    config_host['PKGVERSION'], meson.project_version()]
1636qemu_version = custom_target('qemu-version.h',
1637                             output: 'qemu-version.h',
1638                             command: qemu_version_cmd,
1639                             capture: true,
1640                             build_by_default: true,
1641                             build_always_stale: true)
1642genh += qemu_version
1643
1644hxdep = []
1645hx_headers = [
1646  ['qemu-options.hx', 'qemu-options.def'],
1647  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
1648]
1649if have_system
1650  hx_headers += [
1651    ['hmp-commands.hx', 'hmp-commands.h'],
1652    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
1653  ]
1654endif
1655foreach d : hx_headers
1656  hxdep += custom_target(d[1],
1657                input: files(d[0]),
1658                output: d[1],
1659                capture: true,
1660                build_by_default: true, # to be removed when added to a target
1661                command: [hxtool, '-h', '@INPUT0@'])
1662endforeach
1663genh += hxdep
1664
1665###################
1666# Collect sources #
1667###################
1668
1669authz_ss = ss.source_set()
1670blockdev_ss = ss.source_set()
1671block_ss = ss.source_set()
1672bsd_user_ss = ss.source_set()
1673chardev_ss = ss.source_set()
1674common_ss = ss.source_set()
1675crypto_ss = ss.source_set()
1676io_ss = ss.source_set()
1677linux_user_ss = ss.source_set()
1678qmp_ss = ss.source_set()
1679qom_ss = ss.source_set()
1680softmmu_ss = ss.source_set()
1681specific_fuzz_ss = ss.source_set()
1682specific_ss = ss.source_set()
1683stub_ss = ss.source_set()
1684trace_ss = ss.source_set()
1685user_ss = ss.source_set()
1686util_ss = ss.source_set()
1687
1688modules = {}
1689hw_arch = {}
1690target_arch = {}
1691target_softmmu_arch = {}
1692
1693###############
1694# Trace files #
1695###############
1696
1697# TODO: add each directory to the subdirs from its own meson.build, once
1698# we have those
1699trace_events_subdirs = [
1700  'accel/kvm',
1701  'accel/tcg',
1702  'crypto',
1703  'monitor',
1704]
1705if have_user
1706  trace_events_subdirs += [ 'linux-user' ]
1707endif
1708if have_block
1709  trace_events_subdirs += [
1710    'authz',
1711    'block',
1712    'io',
1713    'nbd',
1714    'scsi',
1715  ]
1716endif
1717if have_system
1718  trace_events_subdirs += [
1719    'audio',
1720    'backends',
1721    'backends/tpm',
1722    'chardev',
1723    'hw/9pfs',
1724    'hw/acpi',
1725    'hw/adc',
1726    'hw/alpha',
1727    'hw/arm',
1728    'hw/audio',
1729    'hw/block',
1730    'hw/block/dataplane',
1731    'hw/char',
1732    'hw/display',
1733    'hw/dma',
1734    'hw/hppa',
1735    'hw/hyperv',
1736    'hw/i2c',
1737    'hw/i386',
1738    'hw/i386/xen',
1739    'hw/ide',
1740    'hw/input',
1741    'hw/intc',
1742    'hw/isa',
1743    'hw/mem',
1744    'hw/mips',
1745    'hw/misc',
1746    'hw/misc/macio',
1747    'hw/net',
1748    'hw/net/can',
1749    'hw/nvram',
1750    'hw/pci',
1751    'hw/pci-host',
1752    'hw/ppc',
1753    'hw/rdma',
1754    'hw/rdma/vmw',
1755    'hw/rtc',
1756    'hw/s390x',
1757    'hw/scsi',
1758    'hw/sd',
1759    'hw/sparc',
1760    'hw/sparc64',
1761    'hw/ssi',
1762    'hw/timer',
1763    'hw/tpm',
1764    'hw/usb',
1765    'hw/vfio',
1766    'hw/virtio',
1767    'hw/watchdog',
1768    'hw/xen',
1769    'hw/gpio',
1770    'migration',
1771    'net',
1772    'softmmu',
1773    'ui',
1774  ]
1775endif
1776trace_events_subdirs += [
1777  'hw/core',
1778  'qapi',
1779  'qom',
1780  'target/arm',
1781  'target/hppa',
1782  'target/i386',
1783  'target/i386/kvm',
1784  'target/mips',
1785  'target/ppc',
1786  'target/riscv',
1787  'target/s390x',
1788  'target/sparc',
1789  'util',
1790]
1791
1792vhost_user = not_found
1793if 'CONFIG_VHOST_USER' in config_host
1794  libvhost_user = subproject('libvhost-user')
1795  vhost_user = libvhost_user.get_variable('vhost_user_dep')
1796endif
1797
1798subdir('qapi')
1799subdir('qobject')
1800subdir('stubs')
1801subdir('trace')
1802subdir('util')
1803subdir('qom')
1804subdir('authz')
1805subdir('crypto')
1806subdir('ui')
1807
1808
1809if enable_modules
1810  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
1811  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
1812endif
1813
1814stub_ss = stub_ss.apply(config_all, strict: false)
1815
1816util_ss.add_all(trace_ss)
1817util_ss = util_ss.apply(config_all, strict: false)
1818libqemuutil = static_library('qemuutil',
1819                             sources: util_ss.sources() + stub_ss.sources() + genh,
1820                             dependencies: [util_ss.dependencies(), m, glib, socket, malloc])
1821qemuutil = declare_dependency(link_with: libqemuutil,
1822                              sources: genh + version_res)
1823
1824decodetree = generator(find_program('scripts/decodetree.py'),
1825                       output: 'decode-@BASENAME@.c.inc',
1826                       arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
1827
1828subdir('audio')
1829subdir('io')
1830subdir('chardev')
1831subdir('fsdev')
1832subdir('libdecnumber')
1833subdir('target')
1834subdir('dump')
1835
1836block_ss.add(files(
1837  'block.c',
1838  'blockjob.c',
1839  'job.c',
1840  'qemu-io-cmds.c',
1841))
1842block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
1843
1844subdir('nbd')
1845subdir('scsi')
1846subdir('block')
1847
1848blockdev_ss.add(files(
1849  'blockdev.c',
1850  'blockdev-nbd.c',
1851  'iothread.c',
1852  'job-qmp.c',
1853), gnutls)
1854
1855# os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
1856# os-win32.c does not
1857blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
1858softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
1859
1860common_ss.add(files('cpus-common.c'))
1861
1862subdir('softmmu')
1863
1864common_ss.add(capstone)
1865specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
1866specific_ss.add(files('exec-vary.c'))
1867specific_ss.add(when: 'CONFIG_TCG', if_true: files(
1868  'fpu/softfloat.c',
1869  'tcg/optimize.c',
1870  'tcg/tcg-common.c',
1871  'tcg/tcg-op-gvec.c',
1872  'tcg/tcg-op-vec.c',
1873  'tcg/tcg-op.c',
1874  'tcg/tcg.c',
1875))
1876specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('disas/tci.c', 'tcg/tci.c'))
1877
1878subdir('backends')
1879subdir('disas')
1880subdir('migration')
1881subdir('monitor')
1882subdir('net')
1883subdir('replay')
1884subdir('hw')
1885subdir('accel')
1886subdir('plugins')
1887subdir('bsd-user')
1888subdir('linux-user')
1889
1890bsd_user_ss.add(files('gdbstub.c'))
1891specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
1892
1893linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
1894specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
1895
1896# needed for fuzzing binaries
1897subdir('tests/qtest/libqos')
1898subdir('tests/qtest/fuzz')
1899
1900########################
1901# Library dependencies #
1902########################
1903
1904block_mods = []
1905softmmu_mods = []
1906foreach d, list : modules
1907  foreach m, module_ss : list
1908    if enable_modules and targetos != 'windows'
1909      module_ss = module_ss.apply(config_all, strict: false)
1910      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
1911                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
1912      if d == 'block'
1913        block_mods += sl
1914      else
1915        softmmu_mods += sl
1916      endif
1917    else
1918      if d == 'block'
1919        block_ss.add_all(module_ss)
1920      else
1921        softmmu_ss.add_all(module_ss)
1922      endif
1923    endif
1924  endforeach
1925endforeach
1926
1927nm = find_program('nm')
1928undefsym = find_program('scripts/undefsym.py')
1929block_syms = custom_target('block.syms', output: 'block.syms',
1930                             input: [libqemuutil, block_mods],
1931                             capture: true,
1932                             command: [undefsym, nm, '@INPUT@'])
1933qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
1934                             input: [libqemuutil, softmmu_mods],
1935                             capture: true,
1936                             command: [undefsym, nm, '@INPUT@'])
1937
1938qom_ss = qom_ss.apply(config_host, strict: false)
1939libqom = static_library('qom', qom_ss.sources() + genh,
1940                        dependencies: [qom_ss.dependencies()],
1941                        name_suffix: 'fa')
1942
1943qom = declare_dependency(link_whole: libqom)
1944
1945authz_ss = authz_ss.apply(config_host, strict: false)
1946libauthz = static_library('authz', authz_ss.sources() + genh,
1947                          dependencies: [authz_ss.dependencies()],
1948                          name_suffix: 'fa',
1949                          build_by_default: false)
1950
1951authz = declare_dependency(link_whole: libauthz,
1952                           dependencies: qom)
1953
1954crypto_ss = crypto_ss.apply(config_host, strict: false)
1955libcrypto = static_library('crypto', crypto_ss.sources() + genh,
1956                           dependencies: [crypto_ss.dependencies()],
1957                           name_suffix: 'fa',
1958                           build_by_default: false)
1959
1960crypto = declare_dependency(link_whole: libcrypto,
1961                            dependencies: [authz, qom])
1962
1963io_ss = io_ss.apply(config_host, strict: false)
1964libio = static_library('io', io_ss.sources() + genh,
1965                       dependencies: [io_ss.dependencies()],
1966                       link_with: libqemuutil,
1967                       name_suffix: 'fa',
1968                       build_by_default: false)
1969
1970io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
1971
1972libmigration = static_library('migration', sources: migration_files + genh,
1973                              name_suffix: 'fa',
1974                              build_by_default: false)
1975migration = declare_dependency(link_with: libmigration,
1976                               dependencies: [zlib, qom, io])
1977softmmu_ss.add(migration)
1978
1979block_ss = block_ss.apply(config_host, strict: false)
1980libblock = static_library('block', block_ss.sources() + genh,
1981                          dependencies: block_ss.dependencies(),
1982                          link_depends: block_syms,
1983                          name_suffix: 'fa',
1984                          build_by_default: false)
1985
1986block = declare_dependency(link_whole: [libblock],
1987                           link_args: '@block.syms',
1988                           dependencies: [crypto, io])
1989
1990blockdev_ss = blockdev_ss.apply(config_host, strict: false)
1991libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
1992                             dependencies: blockdev_ss.dependencies(),
1993                             name_suffix: 'fa',
1994                             build_by_default: false)
1995
1996blockdev = declare_dependency(link_whole: [libblockdev],
1997                              dependencies: [block])
1998
1999qmp_ss = qmp_ss.apply(config_host, strict: false)
2000libqmp = static_library('qmp', qmp_ss.sources() + genh,
2001                        dependencies: qmp_ss.dependencies(),
2002                        name_suffix: 'fa',
2003                        build_by_default: false)
2004
2005qmp = declare_dependency(link_whole: [libqmp])
2006
2007libchardev = static_library('chardev', chardev_ss.sources() + genh,
2008                            name_suffix: 'fa',
2009                            dependencies: [gnutls],
2010                            build_by_default: false)
2011
2012chardev = declare_dependency(link_whole: libchardev)
2013
2014libhwcore = static_library('hwcore', sources: hwcore_files + genh,
2015                           name_suffix: 'fa',
2016                           build_by_default: false)
2017hwcore = declare_dependency(link_whole: libhwcore)
2018common_ss.add(hwcore)
2019
2020###########
2021# Targets #
2022###########
2023
2024foreach m : block_mods + softmmu_mods
2025  shared_module(m.name(),
2026                name_prefix: '',
2027                link_whole: m,
2028                install: true,
2029                install_dir: qemu_moddir)
2030endforeach
2031
2032softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
2033common_ss.add(qom, qemuutil)
2034
2035common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
2036common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
2037
2038common_all = common_ss.apply(config_all, strict: false)
2039common_all = static_library('common',
2040                            build_by_default: false,
2041                            sources: common_all.sources() + genh,
2042                            dependencies: common_all.dependencies(),
2043                            name_suffix: 'fa')
2044
2045feature_to_c = find_program('scripts/feature_to_c.sh')
2046
2047emulators = {}
2048foreach target : target_dirs
2049  config_target = config_target_mak[target]
2050  target_name = config_target['TARGET_NAME']
2051  arch = config_target['TARGET_BASE_ARCH']
2052  arch_srcs = [config_target_h[target]]
2053  arch_deps = []
2054  c_args = ['-DNEED_CPU_H',
2055            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2056            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2057  link_args = emulator_link_args
2058
2059  config_target += config_host
2060  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2061  if targetos == 'linux'
2062    target_inc += include_directories('linux-headers', is_system: true)
2063  endif
2064  if target.endswith('-softmmu')
2065    qemu_target_name = 'qemu-system-' + target_name
2066    target_type='system'
2067    t = target_softmmu_arch[arch].apply(config_target, strict: false)
2068    arch_srcs += t.sources()
2069    arch_deps += t.dependencies()
2070
2071    hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
2072    hw = hw_arch[hw_dir].apply(config_target, strict: false)
2073    arch_srcs += hw.sources()
2074    arch_deps += hw.dependencies()
2075
2076    arch_srcs += config_devices_h[target]
2077    link_args += ['@block.syms', '@qemu.syms']
2078  else
2079    abi = config_target['TARGET_ABI_DIR']
2080    target_type='user'
2081    qemu_target_name = 'qemu-' + target_name
2082    if 'CONFIG_LINUX_USER' in config_target
2083      base_dir = 'linux-user'
2084      target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
2085    else
2086      base_dir = 'bsd-user'
2087      target_inc += include_directories('bsd-user/freebsd')
2088    endif
2089    target_inc += include_directories(
2090      base_dir,
2091      base_dir / abi,
2092    )
2093    if 'CONFIG_LINUX_USER' in config_target
2094      dir = base_dir / abi
2095      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
2096      if config_target.has_key('TARGET_SYSTBL_ABI')
2097        arch_srcs += \
2098          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
2099                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
2100      endif
2101    endif
2102  endif
2103
2104  if 'TARGET_XML_FILES' in config_target
2105    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
2106                                output: target + '-gdbstub-xml.c',
2107                                input: files(config_target['TARGET_XML_FILES'].split()),
2108                                command: [feature_to_c, '@INPUT@'],
2109                                capture: true)
2110    arch_srcs += gdbstub_xml
2111  endif
2112
2113  t = target_arch[arch].apply(config_target, strict: false)
2114  arch_srcs += t.sources()
2115  arch_deps += t.dependencies()
2116
2117  target_common = common_ss.apply(config_target, strict: false)
2118  objects = common_all.extract_objects(target_common.sources())
2119  deps = target_common.dependencies()
2120
2121  target_specific = specific_ss.apply(config_target, strict: false)
2122  arch_srcs += target_specific.sources()
2123  arch_deps += target_specific.dependencies()
2124
2125  lib = static_library('qemu-' + target,
2126                 sources: arch_srcs + genh,
2127                 dependencies: arch_deps,
2128                 objects: objects,
2129                 include_directories: target_inc,
2130                 c_args: c_args,
2131                 build_by_default: false,
2132                 name_suffix: 'fa')
2133
2134  if target.endswith('-softmmu')
2135    execs = [{
2136      'name': 'qemu-system-' + target_name,
2137      'gui': false,
2138      'sources': files('softmmu/main.c'),
2139      'dependencies': []
2140    }]
2141    if targetos == 'windows' and (sdl.found() or gtk.found())
2142      execs += [{
2143        'name': 'qemu-system-' + target_name + 'w',
2144        'gui': true,
2145        'sources': files('softmmu/main.c'),
2146        'dependencies': []
2147      }]
2148    endif
2149    if config_host.has_key('CONFIG_FUZZ')
2150      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
2151      execs += [{
2152        'name': 'qemu-fuzz-' + target_name,
2153        'gui': false,
2154        'sources': specific_fuzz.sources(),
2155        'dependencies': specific_fuzz.dependencies(),
2156      }]
2157    endif
2158  else
2159    execs = [{
2160      'name': 'qemu-' + target_name,
2161      'gui': false,
2162      'sources': [],
2163      'dependencies': []
2164    }]
2165  endif
2166  foreach exe: execs
2167    emulators += {exe['name']:
2168         executable(exe['name'], exe['sources'],
2169               install: true,
2170               c_args: c_args,
2171               dependencies: arch_deps + deps + exe['dependencies'],
2172               objects: lib.extract_all_objects(recursive: true),
2173               link_language: link_language,
2174               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
2175               link_args: link_args,
2176               gui_app: exe['gui'])
2177    }
2178
2179    if 'CONFIG_TRACE_SYSTEMTAP' in config_host
2180      foreach stp: [
2181        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
2182        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
2183        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
2184        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
2185      ]
2186        custom_target(exe['name'] + stp['ext'],
2187                      input: trace_events_all,
2188                      output: exe['name'] + stp['ext'],
2189                      install: stp['install'],
2190                      install_dir: get_option('datadir') / 'systemtap/tapset',
2191                      command: [
2192                        tracetool, '--group=all', '--format=' + stp['fmt'],
2193                        '--binary=' + stp['bin'],
2194                        '--target-name=' + target_name,
2195                        '--target-type=' + target_type,
2196                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
2197                        '@INPUT@', '@OUTPUT@'
2198                      ])
2199      endforeach
2200    endif
2201  endforeach
2202endforeach
2203
2204# Other build targets
2205
2206if 'CONFIG_PLUGIN' in config_host
2207  install_headers('include/qemu/qemu-plugin.h')
2208endif
2209
2210if 'CONFIG_GUEST_AGENT' in config_host
2211  subdir('qga')
2212elif get_option('guest_agent_msi').enabled()
2213  error('Guest agent MSI requested, but the guest agent is not being built')
2214endif
2215
2216# Don't build qemu-keymap if xkbcommon is not explicitly enabled
2217# when we don't build tools or system
2218if xkbcommon.found()
2219  # used for the update-keymaps target, so include rules even if !have_tools
2220  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
2221                           dependencies: [qemuutil, xkbcommon], install: have_tools)
2222endif
2223
2224if have_tools
2225  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
2226             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
2227  qemu_io = executable('qemu-io', files('qemu-io.c'),
2228             dependencies: [block, qemuutil], install: true)
2229  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
2230               dependencies: [blockdev, qemuutil, gnutls], install: true)
2231
2232  subdir('storage-daemon')
2233  subdir('contrib/rdmacm-mux')
2234  subdir('contrib/elf2dmp')
2235
2236  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
2237             dependencies: qemuutil,
2238             install: true)
2239
2240  if 'CONFIG_VHOST_USER' in config_host
2241    subdir('contrib/vhost-user-blk')
2242    subdir('contrib/vhost-user-gpu')
2243    subdir('contrib/vhost-user-input')
2244    subdir('contrib/vhost-user-scsi')
2245  endif
2246
2247  if targetos == 'linux'
2248    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
2249               dependencies: [qemuutil, libcap_ng],
2250               install: true,
2251               install_dir: get_option('libexecdir'))
2252
2253    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
2254               dependencies: [authz, crypto, io, qom, qemuutil,
2255                              libcap_ng, mpathpersist],
2256               install: true)
2257  endif
2258
2259  if 'CONFIG_IVSHMEM' in config_host
2260    subdir('contrib/ivshmem-client')
2261    subdir('contrib/ivshmem-server')
2262  endif
2263endif
2264
2265subdir('scripts')
2266subdir('tools')
2267subdir('pc-bios')
2268subdir('docs')
2269subdir('tests')
2270if gtk.found()
2271  subdir('po')
2272endif
2273
2274if host_machine.system() == 'windows'
2275  nsis_cmd = [
2276    find_program('scripts/nsis.py'),
2277    '@OUTPUT@',
2278    get_option('prefix'),
2279    meson.current_source_dir(),
2280    host_machine.cpu(),
2281    '--',
2282    '-DDISPLAYVERSION=' + meson.project_version(),
2283  ]
2284  if build_docs
2285    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
2286  endif
2287  if gtk.found()
2288    nsis_cmd += '-DCONFIG_GTK=y'
2289  endif
2290
2291  nsis = custom_target('nsis',
2292                       output: 'qemu-setup-' + meson.project_version() + '.exe',
2293                       input: files('qemu.nsi'),
2294                       build_always_stale: true,
2295                       command: nsis_cmd + ['@INPUT@'])
2296  alias_target('installer', nsis)
2297endif
2298
2299#########################
2300# Configuration summary #
2301#########################
2302
2303# Directories
2304summary_info = {}
2305summary_info += {'Install prefix':    get_option('prefix')}
2306summary_info += {'BIOS directory':    qemu_datadir}
2307summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
2308summary_info += {'binary directory':  get_option('bindir')}
2309summary_info += {'library directory': get_option('libdir')}
2310summary_info += {'module directory':  qemu_moddir}
2311summary_info += {'libexec directory': get_option('libexecdir')}
2312summary_info += {'include directory': get_option('includedir')}
2313summary_info += {'config directory':  get_option('sysconfdir')}
2314if targetos != 'windows'
2315  summary_info += {'local state directory': get_option('localstatedir')}
2316  summary_info += {'Manual directory':      get_option('mandir')}
2317else
2318  summary_info += {'local state directory': 'queried at runtime'}
2319endif
2320summary_info += {'Doc directory':     get_option('docdir')}
2321summary_info += {'Build directory':   meson.current_build_dir()}
2322summary_info += {'Source path':       meson.current_source_dir()}
2323summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
2324summary(summary_info, bool_yn: true, section: 'Directories')
2325
2326# Host binaries
2327summary_info = {}
2328summary_info += {'git':               config_host['GIT']}
2329summary_info += {'make':              config_host['MAKE']}
2330summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
2331summary_info += {'sphinx-build':      sphinx_build.found()}
2332if config_host.has_key('HAVE_GDB_BIN')
2333  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
2334endif
2335summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
2336if targetos == 'windows' and config_host.has_key('CONFIG_GUEST_AGENT')
2337  summary_info += {'wixl':            wixl.found() ? wixl.full_path() : false}
2338endif
2339if slirp_opt != 'disabled'
2340  summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
2341endif
2342summary(summary_info, bool_yn: true, section: 'Host binaries')
2343
2344# Configurable features
2345summary_info = {}
2346summary_info += {'Documentation':     build_docs}
2347summary_info += {'system-mode emulation': have_system}
2348summary_info += {'user-mode emulation': have_user}
2349summary_info += {'block layer':       have_block}
2350summary_info += {'Install blobs':     get_option('install_blobs')}
2351summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
2352if config_host.has_key('CONFIG_MODULES')
2353  summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
2354endif
2355summary_info += {'plugin support':    config_host.has_key('CONFIG_PLUGIN')}
2356summary_info += {'fuzzing support':   config_host.has_key('CONFIG_FUZZ')}
2357if have_system
2358  summary_info += {'Audio drivers':     config_host['CONFIG_AUDIO_DRIVERS']}
2359endif
2360summary_info += {'Trace backends':    config_host['TRACE_BACKENDS']}
2361if config_host['TRACE_BACKENDS'].split().contains('simple')
2362  summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-<pid>'}
2363endif
2364summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
2365summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
2366summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
2367summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
2368summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
2369summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
2370summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
2371summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
2372summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
2373summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
2374summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
2375summary(summary_info, bool_yn: true, section: 'Configurable features')
2376
2377# Compilation information
2378summary_info = {}
2379summary_info += {'host CPU':          cpu}
2380summary_info += {'host endianness':   build_machine.endian()}
2381summary_info += {'C compiler':        meson.get_compiler('c').cmd_array()[0]}
2382summary_info += {'Host C compiler':   meson.get_compiler('c', native: true).cmd_array()[0]}
2383if link_language == 'cpp'
2384  summary_info += {'C++ compiler':      meson.get_compiler('cpp').cmd_array()[0]}
2385else
2386  summary_info += {'C++ compiler':      false}
2387endif
2388if targetos == 'darwin'
2389  summary_info += {'Objective-C compiler': meson.get_compiler('objc').cmd_array()[0]}
2390endif
2391if targetos == 'windows'
2392  if 'WIN_SDK' in config_host
2393    summary_info += {'Windows SDK':   config_host['WIN_SDK']}
2394  endif
2395endif
2396summary_info += {'ARFLAGS':           config_host['ARFLAGS']}
2397summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
2398                                               + ['-O' + get_option('optimization')]
2399                                               + (get_option('debug') ? ['-g'] : []))}
2400if link_language == 'cpp'
2401  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
2402                                               + ['-O' + get_option('optimization')]
2403                                               + (get_option('debug') ? ['-g'] : []))}
2404endif
2405link_args = get_option(link_language + '_link_args')
2406if link_args.length() > 0
2407  summary_info += {'LDFLAGS':         ' '.join(link_args)}
2408endif
2409summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
2410summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
2411summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
2412summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
2413summary_info += {'PIE':               get_option('b_pie')}
2414summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
2415summary_info += {'malloc trim support': has_malloc_trim}
2416summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
2417summary_info += {'preadv support':    config_host.has_key('CONFIG_PREADV')}
2418summary_info += {'fdatasync':         config_host.has_key('CONFIG_FDATASYNC')}
2419summary_info += {'madvise':           config_host.has_key('CONFIG_MADVISE')}
2420summary_info += {'posix_madvise':     config_host.has_key('CONFIG_POSIX_MADVISE')}
2421summary_info += {'posix_memalign':    config_host.has_key('CONFIG_POSIX_MEMALIGN')}
2422summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
2423summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
2424summary_info += {'memory allocator':  get_option('malloc')}
2425summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
2426summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
2427summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
2428summary_info += {'gcov':              get_option('b_coverage')}
2429summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
2430summary_info += {'CFI support':       get_option('cfi')}
2431if get_option('cfi')
2432  summary_info += {'CFI debug support': get_option('cfi_debug')}
2433endif
2434summary_info += {'strip binaries':    get_option('strip')}
2435summary_info += {'sparse':            sparse.found() ? sparse.full_path() : false}
2436summary_info += {'mingw32 support':   targetos == 'windows'}
2437summary(summary_info, bool_yn: true, section: 'Compilation')
2438
2439# Targets and accelerators
2440summary_info = {}
2441if have_system
2442  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
2443  summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
2444  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
2445  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
2446  summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
2447  if config_host.has_key('CONFIG_XEN_BACKEND')
2448    summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
2449  endif
2450endif
2451summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
2452if config_all.has_key('CONFIG_TCG')
2453  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
2454  summary_info += {'TCG interpreter':   tcg_arch == 'tci'}
2455endif
2456summary_info += {'target list':       ' '.join(target_dirs)}
2457if have_system
2458  summary_info += {'default devices':   get_option('default_devices')}
2459endif
2460summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
2461
2462# Block layer
2463summary_info = {}
2464summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
2465summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
2466if have_block
2467  summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
2468  summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
2469  summary_info += {'VirtFS support':    have_virtfs}
2470  summary_info += {'build virtiofs daemon': have_virtiofsd}
2471  summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
2472  summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
2473  summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
2474  summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
2475  summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
2476  summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
2477  summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
2478  summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
2479  summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
2480  summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
2481  summary_info += {'sheepdog support':  config_host.has_key('CONFIG_SHEEPDOG')}
2482  summary_info += {'FUSE exports':      fuse.found()}
2483endif
2484summary(summary_info, bool_yn: true, section: 'Block layer support')
2485
2486# Crypto
2487summary_info = {}
2488summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
2489summary_info += {'GNUTLS support':    config_host.has_key('CONFIG_GNUTLS')}
2490# TODO: add back version
2491summary_info += {'libgcrypt':         config_host.has_key('CONFIG_GCRYPT')}
2492if config_host.has_key('CONFIG_GCRYPT')
2493   summary_info += {'  hmac':            config_host.has_key('CONFIG_GCRYPT_HMAC')}
2494   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2495endif
2496# TODO: add back version
2497summary_info += {'nettle':            config_host.has_key('CONFIG_NETTLE')}
2498if config_host.has_key('CONFIG_NETTLE')
2499   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2500endif
2501summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
2502summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
2503summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
2504summary(summary_info, bool_yn: true, section: 'Crypto')
2505
2506# Libraries
2507summary_info = {}
2508if targetos == 'darwin'
2509  summary_info += {'Cocoa support':   cocoa.found()}
2510endif
2511# TODO: add back version
2512summary_info += {'SDL support':       sdl.found()}
2513summary_info += {'SDL image support': sdl_image.found()}
2514# TODO: add back version
2515summary_info += {'GTK support':       gtk.found()}
2516summary_info += {'pixman':            pixman.found()}
2517# TODO: add back version
2518summary_info += {'VTE support':       config_host.has_key('CONFIG_VTE')}
2519# TODO: add back version
2520summary_info += {'slirp support':     slirp_opt == 'disabled' ? false : slirp_opt}
2521summary_info += {'libtasn1':          config_host.has_key('CONFIG_TASN1')}
2522summary_info += {'PAM':               config_host.has_key('CONFIG_AUTH_PAM')}
2523summary_info += {'iconv support':     iconv.found()}
2524summary_info += {'curses support':    curses.found()}
2525# TODO: add back version
2526summary_info += {'virgl support':     config_host.has_key('CONFIG_VIRGL')}
2527summary_info += {'curl support':      curl.found()}
2528summary_info += {'Multipath support': mpathpersist.found()}
2529summary_info += {'VNC support':       vnc.found()}
2530if vnc.found()
2531  summary_info += {'VNC SASL support':  sasl.found()}
2532  summary_info += {'VNC JPEG support':  jpeg.found()}
2533  summary_info += {'VNC PNG support':   png.found()}
2534endif
2535summary_info += {'brlapi support':    brlapi.found()}
2536summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
2537summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
2538summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
2539summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')}
2540summary_info += {'ATTR/XATTR support': libattr.found()}
2541summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
2542summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
2543summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
2544summary_info += {'libcap-ng support': libcap_ng.found()}
2545# TODO: add back protocol and server version
2546summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
2547summary_info += {'rbd support':       rbd.found()}
2548summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
2549summary_info += {'smartcard support': config_host.has_key('CONFIG_SMARTCARD')}
2550summary_info += {'U2F support':       u2f.found()}
2551summary_info += {'libusb':            config_host.has_key('CONFIG_USB_LIBUSB')}
2552summary_info += {'usb net redir':     config_host.has_key('CONFIG_USB_REDIR')}
2553summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
2554summary_info += {'OpenGL dmabufs':    config_host.has_key('CONFIG_OPENGL_DMABUF')}
2555summary_info += {'libiscsi support':  libiscsi.found()}
2556summary_info += {'libnfs support':    libnfs.found()}
2557if targetos == 'windows'
2558  if config_host.has_key('CONFIG_GUEST_AGENT')
2559    summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
2560    summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
2561  endif
2562endif
2563summary_info += {'seccomp support':   seccomp.found()}
2564summary_info += {'GlusterFS support': glusterfs.found()}
2565summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
2566summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
2567summary_info += {'lzo support':       lzo.found()}
2568summary_info += {'snappy support':    snappy.found()}
2569summary_info += {'bzip2 support':     libbzip2.found()}
2570summary_info += {'lzfse support':     liblzfse.found()}
2571summary_info += {'zstd support':      zstd.found()}
2572summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
2573summary_info += {'libxml2':           config_host.has_key('CONFIG_LIBXML2')}
2574summary_info += {'capstone':          capstone_opt == 'disabled' ? false : capstone_opt}
2575summary_info += {'libpmem support':   config_host.has_key('CONFIG_LIBPMEM')}
2576summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')}
2577summary_info += {'libudev':           libudev.found()}
2578summary_info += {'FUSE lseek':        fuse_lseek.found()}
2579summary(summary_info, bool_yn: true, section: 'Dependencies')
2580
2581if not supported_cpus.contains(cpu)
2582  message()
2583  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
2584  message()
2585  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
2586  message('The QEMU project intends to remove support for this host CPU in')
2587  message('a future release if nobody volunteers to maintain it and to')
2588  message('provide a build host for our continuous integration setup.')
2589  message('configure has succeeded and you can continue to build, but')
2590  message('if you care about QEMU on this platform you should contact')
2591  message('us upstream at qemu-devel@nongnu.org.')
2592endif
2593
2594if not supported_oses.contains(targetos)
2595  message()
2596  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
2597  message()
2598  message('Host OS ' + targetos + 'support is not currently maintained.')
2599  message('The QEMU project intends to remove support for this host OS in')
2600  message('a future release if nobody volunteers to maintain it and to')
2601  message('provide a build host for our continuous integration setup.')
2602  message('configure has succeeded and you can continue to build, but')
2603  message('if you care about QEMU on this platform you should contact')
2604  message('us upstream at qemu-devel@nongnu.org.')
2605endif
2606