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