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