xref: /openbmc/qemu/meson.build (revision ad1a706f)
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/sparc',
2106  ]
2107endif
2108
2109vhost_user = not_found
2110if 'CONFIG_VHOST_USER' in config_host
2111  libvhost_user = subproject('libvhost-user')
2112  vhost_user = libvhost_user.get_variable('vhost_user_dep')
2113endif
2114
2115subdir('qapi')
2116subdir('qobject')
2117subdir('stubs')
2118subdir('trace')
2119subdir('util')
2120subdir('qom')
2121subdir('authz')
2122subdir('crypto')
2123subdir('ui')
2124
2125
2126if enable_modules
2127  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
2128  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
2129endif
2130
2131stub_ss = stub_ss.apply(config_all, strict: false)
2132
2133util_ss.add_all(trace_ss)
2134util_ss = util_ss.apply(config_all, strict: false)
2135libqemuutil = static_library('qemuutil',
2136                             sources: util_ss.sources() + stub_ss.sources() + genh,
2137                             dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
2138qemuutil = declare_dependency(link_with: libqemuutil,
2139                              sources: genh + version_res)
2140
2141if have_system or have_user
2142  decodetree = generator(find_program('scripts/decodetree.py'),
2143                         output: 'decode-@BASENAME@.c.inc',
2144                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
2145  subdir('libdecnumber')
2146  subdir('target')
2147endif
2148
2149subdir('audio')
2150subdir('io')
2151subdir('chardev')
2152subdir('fsdev')
2153subdir('dump')
2154
2155if have_block
2156  block_ss.add(files(
2157    'block.c',
2158    'blockjob.c',
2159    'job.c',
2160    'qemu-io-cmds.c',
2161  ))
2162  block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
2163
2164  subdir('nbd')
2165  subdir('scsi')
2166  subdir('block')
2167
2168  blockdev_ss.add(files(
2169    'blockdev.c',
2170    'blockdev-nbd.c',
2171    'iothread.c',
2172    'job-qmp.c',
2173  ), gnutls)
2174
2175  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
2176  # os-win32.c does not
2177  blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
2178  softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
2179endif
2180
2181common_ss.add(files('cpus-common.c'))
2182
2183subdir('softmmu')
2184
2185common_ss.add(capstone)
2186specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
2187
2188# Work around a gcc bug/misfeature wherein constant propagation looks
2189# through an alias:
2190#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
2191# to guess that a const variable is always zero.  Without lto, this is
2192# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
2193# without lto, not even the alias is required -- we simply use different
2194# declarations in different compilation units.
2195pagevary = files('page-vary-common.c')
2196if get_option('b_lto')
2197  pagevary_flags = ['-fno-lto']
2198  if get_option('cfi')
2199    pagevary_flags += '-fno-sanitize=cfi-icall'
2200  endif
2201  pagevary = static_library('page-vary-common', sources: pagevary,
2202                            c_args: pagevary_flags)
2203  pagevary = declare_dependency(link_with: pagevary)
2204endif
2205common_ss.add(pagevary)
2206specific_ss.add(files('page-vary.c'))
2207
2208subdir('backends')
2209subdir('disas')
2210subdir('migration')
2211subdir('monitor')
2212subdir('net')
2213subdir('replay')
2214subdir('semihosting')
2215subdir('hw')
2216subdir('tcg')
2217subdir('fpu')
2218subdir('accel')
2219subdir('plugins')
2220subdir('bsd-user')
2221subdir('linux-user')
2222subdir('ebpf')
2223
2224common_ss.add(libbpf)
2225
2226bsd_user_ss.add(files('gdbstub.c'))
2227specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
2228
2229linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
2230specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
2231
2232# needed for fuzzing binaries
2233subdir('tests/qtest/libqos')
2234subdir('tests/qtest/fuzz')
2235
2236########################
2237# Library dependencies #
2238########################
2239
2240block_mods = []
2241softmmu_mods = []
2242foreach d, list : modules
2243  foreach m, module_ss : list
2244    if enable_modules and targetos != 'windows'
2245      module_ss = module_ss.apply(config_all, strict: false)
2246      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
2247                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
2248      if d == 'block'
2249        block_mods += sl
2250      else
2251        softmmu_mods += sl
2252      endif
2253    else
2254      if d == 'block'
2255        block_ss.add_all(module_ss)
2256      else
2257        softmmu_ss.add_all(module_ss)
2258      endif
2259    endif
2260  endforeach
2261endforeach
2262
2263nm = find_program('nm')
2264undefsym = find_program('scripts/undefsym.py')
2265block_syms = custom_target('block.syms', output: 'block.syms',
2266                             input: [libqemuutil, block_mods],
2267                             capture: true,
2268                             command: [undefsym, nm, '@INPUT@'])
2269qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
2270                             input: [libqemuutil, softmmu_mods],
2271                             capture: true,
2272                             command: [undefsym, nm, '@INPUT@'])
2273
2274qom_ss = qom_ss.apply(config_host, strict: false)
2275libqom = static_library('qom', qom_ss.sources() + genh,
2276                        dependencies: [qom_ss.dependencies()],
2277                        name_suffix: 'fa')
2278
2279qom = declare_dependency(link_whole: libqom)
2280
2281authz_ss = authz_ss.apply(config_host, strict: false)
2282libauthz = static_library('authz', authz_ss.sources() + genh,
2283                          dependencies: [authz_ss.dependencies()],
2284                          name_suffix: 'fa',
2285                          build_by_default: false)
2286
2287authz = declare_dependency(link_whole: libauthz,
2288                           dependencies: qom)
2289
2290crypto_ss = crypto_ss.apply(config_host, strict: false)
2291libcrypto = static_library('crypto', crypto_ss.sources() + genh,
2292                           dependencies: [crypto_ss.dependencies()],
2293                           name_suffix: 'fa',
2294                           build_by_default: false)
2295
2296crypto = declare_dependency(link_whole: libcrypto,
2297                            dependencies: [authz, qom])
2298
2299io_ss = io_ss.apply(config_host, strict: false)
2300libio = static_library('io', io_ss.sources() + genh,
2301                       dependencies: [io_ss.dependencies()],
2302                       link_with: libqemuutil,
2303                       name_suffix: 'fa',
2304                       build_by_default: false)
2305
2306io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
2307
2308libmigration = static_library('migration', sources: migration_files + genh,
2309                              name_suffix: 'fa',
2310                              build_by_default: false)
2311migration = declare_dependency(link_with: libmigration,
2312                               dependencies: [zlib, qom, io])
2313softmmu_ss.add(migration)
2314
2315block_ss = block_ss.apply(config_host, strict: false)
2316libblock = static_library('block', block_ss.sources() + genh,
2317                          dependencies: block_ss.dependencies(),
2318                          link_depends: block_syms,
2319                          name_suffix: 'fa',
2320                          build_by_default: false)
2321
2322block = declare_dependency(link_whole: [libblock],
2323                           link_args: '@block.syms',
2324                           dependencies: [crypto, io])
2325
2326blockdev_ss = blockdev_ss.apply(config_host, strict: false)
2327libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
2328                             dependencies: blockdev_ss.dependencies(),
2329                             name_suffix: 'fa',
2330                             build_by_default: false)
2331
2332blockdev = declare_dependency(link_whole: [libblockdev],
2333                              dependencies: [block])
2334
2335qmp_ss = qmp_ss.apply(config_host, strict: false)
2336libqmp = static_library('qmp', qmp_ss.sources() + genh,
2337                        dependencies: qmp_ss.dependencies(),
2338                        name_suffix: 'fa',
2339                        build_by_default: false)
2340
2341qmp = declare_dependency(link_whole: [libqmp])
2342
2343libchardev = static_library('chardev', chardev_ss.sources() + genh,
2344                            name_suffix: 'fa',
2345                            dependencies: [gnutls],
2346                            build_by_default: false)
2347
2348chardev = declare_dependency(link_whole: libchardev)
2349
2350libhwcore = static_library('hwcore', sources: hwcore_files + genh,
2351                           name_suffix: 'fa',
2352                           build_by_default: false)
2353hwcore = declare_dependency(link_whole: libhwcore)
2354common_ss.add(hwcore)
2355
2356###########
2357# Targets #
2358###########
2359
2360foreach m : block_mods + softmmu_mods
2361  shared_module(m.name(),
2362                name_prefix: '',
2363                link_whole: m,
2364                install: true,
2365                install_dir: qemu_moddir)
2366endforeach
2367
2368softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
2369common_ss.add(qom, qemuutil)
2370
2371common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
2372common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
2373
2374common_all = common_ss.apply(config_all, strict: false)
2375common_all = static_library('common',
2376                            build_by_default: false,
2377                            sources: common_all.sources() + genh,
2378                            implicit_include_directories: false,
2379                            dependencies: common_all.dependencies(),
2380                            name_suffix: 'fa')
2381
2382feature_to_c = find_program('scripts/feature_to_c.sh')
2383
2384emulators = {}
2385foreach target : target_dirs
2386  config_target = config_target_mak[target]
2387  target_name = config_target['TARGET_NAME']
2388  arch = config_target['TARGET_BASE_ARCH']
2389  arch_srcs = [config_target_h[target]]
2390  arch_deps = []
2391  c_args = ['-DNEED_CPU_H',
2392            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2393            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2394  link_args = emulator_link_args
2395
2396  config_target += config_host
2397  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2398  if targetos == 'linux'
2399    target_inc += include_directories('linux-headers', is_system: true)
2400  endif
2401  if target.endswith('-softmmu')
2402    qemu_target_name = 'qemu-system-' + target_name
2403    target_type='system'
2404    t = target_softmmu_arch[arch].apply(config_target, strict: false)
2405    arch_srcs += t.sources()
2406    arch_deps += t.dependencies()
2407
2408    hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
2409    hw = hw_arch[hw_dir].apply(config_target, strict: false)
2410    arch_srcs += hw.sources()
2411    arch_deps += hw.dependencies()
2412
2413    arch_srcs += config_devices_h[target]
2414    link_args += ['@block.syms', '@qemu.syms']
2415  else
2416    abi = config_target['TARGET_ABI_DIR']
2417    target_type='user'
2418    qemu_target_name = 'qemu-' + target_name
2419    if arch in target_user_arch
2420      t = target_user_arch[arch].apply(config_target, strict: false)
2421      arch_srcs += t.sources()
2422      arch_deps += t.dependencies()
2423    endif
2424    if 'CONFIG_LINUX_USER' in config_target
2425      base_dir = 'linux-user'
2426      target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
2427    else
2428      base_dir = 'bsd-user'
2429      target_inc += include_directories('bsd-user/freebsd')
2430    endif
2431    target_inc += include_directories(
2432      base_dir,
2433      base_dir / abi,
2434    )
2435    if 'CONFIG_LINUX_USER' in config_target
2436      dir = base_dir / abi
2437      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
2438      if config_target.has_key('TARGET_SYSTBL_ABI')
2439        arch_srcs += \
2440          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
2441                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
2442      endif
2443    endif
2444  endif
2445
2446  if 'TARGET_XML_FILES' in config_target
2447    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
2448                                output: target + '-gdbstub-xml.c',
2449                                input: files(config_target['TARGET_XML_FILES'].split()),
2450                                command: [feature_to_c, '@INPUT@'],
2451                                capture: true)
2452    arch_srcs += gdbstub_xml
2453  endif
2454
2455  t = target_arch[arch].apply(config_target, strict: false)
2456  arch_srcs += t.sources()
2457  arch_deps += t.dependencies()
2458
2459  target_common = common_ss.apply(config_target, strict: false)
2460  objects = common_all.extract_objects(target_common.sources())
2461  deps = target_common.dependencies()
2462
2463  target_specific = specific_ss.apply(config_target, strict: false)
2464  arch_srcs += target_specific.sources()
2465  arch_deps += target_specific.dependencies()
2466
2467  lib = static_library('qemu-' + target,
2468                 sources: arch_srcs + genh,
2469                 dependencies: arch_deps,
2470                 objects: objects,
2471                 include_directories: target_inc,
2472                 c_args: c_args,
2473                 build_by_default: false,
2474                 name_suffix: 'fa')
2475
2476  if target.endswith('-softmmu')
2477    execs = [{
2478      'name': 'qemu-system-' + target_name,
2479      'gui': false,
2480      'sources': files('softmmu/main.c'),
2481      'dependencies': []
2482    }]
2483    if targetos == 'windows' and (sdl.found() or gtk.found())
2484      execs += [{
2485        'name': 'qemu-system-' + target_name + 'w',
2486        'gui': true,
2487        'sources': files('softmmu/main.c'),
2488        'dependencies': []
2489      }]
2490    endif
2491    if config_host.has_key('CONFIG_FUZZ')
2492      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
2493      execs += [{
2494        'name': 'qemu-fuzz-' + target_name,
2495        'gui': false,
2496        'sources': specific_fuzz.sources(),
2497        'dependencies': specific_fuzz.dependencies(),
2498      }]
2499    endif
2500  else
2501    execs = [{
2502      'name': 'qemu-' + target_name,
2503      'gui': false,
2504      'sources': [],
2505      'dependencies': []
2506    }]
2507  endif
2508  foreach exe: execs
2509    exe_name = exe['name']
2510    if targetos == 'darwin'
2511      exe_name += '-unsigned'
2512    endif
2513
2514    emulator = executable(exe_name, exe['sources'],
2515               install: true,
2516               c_args: c_args,
2517               dependencies: arch_deps + deps + exe['dependencies'],
2518               objects: lib.extract_all_objects(recursive: true),
2519               link_language: link_language,
2520               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
2521               link_args: link_args,
2522               gui_app: exe['gui'])
2523
2524    if 'CONFIG_HVF' in config_target
2525      entitlements = meson.current_source_dir() / 'accel/hvf/entitlements.plist'
2526    else
2527      entitlements = '/dev/null'
2528    endif
2529    if targetos == 'darwin'
2530      icon = meson.current_source_dir() / 'pc-bios/qemu.rsrc'
2531      emulators += {exe['name'] : custom_target(exe['name'],
2532                   depends: emulator,
2533                   output: exe['name'],
2534                   command: [
2535                     meson.current_source_dir() / 'scripts/entitlement.sh',
2536                     meson.current_build_dir() / exe_name,
2537                     meson.current_build_dir() / exe['name'],
2538                     entitlements, icon
2539                   ])
2540      }
2541
2542      meson.add_install_script('scripts/entitlement.sh', '--install',
2543                               get_option('bindir') / exe_name,
2544                               get_option('bindir') / exe['name'],
2545                               entitlements, icon)
2546    else
2547      emulators += {exe['name']: emulator}
2548    endif
2549
2550    if 'CONFIG_TRACE_SYSTEMTAP' in config_host
2551      foreach stp: [
2552        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
2553        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
2554        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
2555        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
2556      ]
2557        custom_target(exe['name'] + stp['ext'],
2558                      input: trace_events_all,
2559                      output: exe['name'] + stp['ext'],
2560                      install: stp['install'],
2561                      install_dir: get_option('datadir') / 'systemtap/tapset',
2562                      command: [
2563                        tracetool, '--group=all', '--format=' + stp['fmt'],
2564                        '--binary=' + stp['bin'],
2565                        '--target-name=' + target_name,
2566                        '--target-type=' + target_type,
2567                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
2568                        '@INPUT@', '@OUTPUT@'
2569                      ],
2570                      depend_files: tracetool_depends)
2571      endforeach
2572    endif
2573  endforeach
2574endforeach
2575
2576# Other build targets
2577
2578if 'CONFIG_PLUGIN' in config_host
2579  install_headers('include/qemu/qemu-plugin.h')
2580endif
2581
2582if 'CONFIG_GUEST_AGENT' in config_host
2583  subdir('qga')
2584elif get_option('guest_agent_msi').enabled()
2585  error('Guest agent MSI requested, but the guest agent is not being built')
2586endif
2587
2588# Don't build qemu-keymap if xkbcommon is not explicitly enabled
2589# when we don't build tools or system
2590if xkbcommon.found()
2591  # used for the update-keymaps target, so include rules even if !have_tools
2592  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
2593                           dependencies: [qemuutil, xkbcommon], install: have_tools)
2594endif
2595
2596if have_tools
2597  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
2598             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
2599  qemu_io = executable('qemu-io', files('qemu-io.c'),
2600             dependencies: [block, qemuutil], install: true)
2601  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
2602               dependencies: [blockdev, qemuutil, gnutls], install: true)
2603
2604  subdir('storage-daemon')
2605  subdir('contrib/rdmacm-mux')
2606  subdir('contrib/elf2dmp')
2607
2608  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
2609             dependencies: qemuutil,
2610             install: true)
2611
2612  if 'CONFIG_VHOST_USER' in config_host
2613    subdir('contrib/vhost-user-blk')
2614    subdir('contrib/vhost-user-gpu')
2615    subdir('contrib/vhost-user-input')
2616    subdir('contrib/vhost-user-scsi')
2617  endif
2618
2619  if targetos == 'linux'
2620    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
2621               dependencies: [qemuutil, libcap_ng],
2622               install: true,
2623               install_dir: get_option('libexecdir'))
2624
2625    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
2626               dependencies: [authz, crypto, io, qom, qemuutil,
2627                              libcap_ng, mpathpersist],
2628               install: true)
2629  endif
2630
2631  if have_ivshmem
2632    subdir('contrib/ivshmem-client')
2633    subdir('contrib/ivshmem-server')
2634  endif
2635endif
2636
2637subdir('scripts')
2638subdir('tools')
2639subdir('pc-bios')
2640subdir('docs')
2641subdir('tests')
2642if gtk.found()
2643  subdir('po')
2644endif
2645
2646if host_machine.system() == 'windows'
2647  nsis_cmd = [
2648    find_program('scripts/nsis.py'),
2649    '@OUTPUT@',
2650    get_option('prefix'),
2651    meson.current_source_dir(),
2652    host_machine.cpu(),
2653    '--',
2654    '-DDISPLAYVERSION=' + meson.project_version(),
2655  ]
2656  if build_docs
2657    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
2658  endif
2659  if gtk.found()
2660    nsis_cmd += '-DCONFIG_GTK=y'
2661  endif
2662
2663  nsis = custom_target('nsis',
2664                       output: 'qemu-setup-' + meson.project_version() + '.exe',
2665                       input: files('qemu.nsi'),
2666                       build_always_stale: true,
2667                       command: nsis_cmd + ['@INPUT@'])
2668  alias_target('installer', nsis)
2669endif
2670
2671#########################
2672# Configuration summary #
2673#########################
2674
2675# Directories
2676summary_info = {}
2677summary_info += {'Install prefix':    get_option('prefix')}
2678summary_info += {'BIOS directory':    qemu_datadir}
2679summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
2680summary_info += {'binary directory':  get_option('bindir')}
2681summary_info += {'library directory': get_option('libdir')}
2682summary_info += {'module directory':  qemu_moddir}
2683summary_info += {'libexec directory': get_option('libexecdir')}
2684summary_info += {'include directory': get_option('includedir')}
2685summary_info += {'config directory':  get_option('sysconfdir')}
2686if targetos != 'windows'
2687  summary_info += {'local state directory': get_option('localstatedir')}
2688  summary_info += {'Manual directory':      get_option('mandir')}
2689else
2690  summary_info += {'local state directory': 'queried at runtime'}
2691endif
2692summary_info += {'Doc directory':     get_option('docdir')}
2693summary_info += {'Build directory':   meson.current_build_dir()}
2694summary_info += {'Source path':       meson.current_source_dir()}
2695summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
2696summary(summary_info, bool_yn: true, section: 'Directories')
2697
2698# Host binaries
2699summary_info = {}
2700summary_info += {'git':               config_host['GIT']}
2701summary_info += {'make':              config_host['MAKE']}
2702summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
2703summary_info += {'sphinx-build':      sphinx_build.found()}
2704if config_host.has_key('HAVE_GDB_BIN')
2705  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
2706endif
2707summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
2708if targetos == 'windows' and config_host.has_key('CONFIG_GUEST_AGENT')
2709  summary_info += {'wixl':            wixl.found() ? wixl.full_path() : false}
2710endif
2711if slirp_opt != 'disabled' and 'CONFIG_SLIRP_SMBD' in config_host
2712  summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
2713endif
2714summary(summary_info, bool_yn: true, section: 'Host binaries')
2715
2716# Configurable features
2717summary_info = {}
2718summary_info += {'Documentation':     build_docs}
2719summary_info += {'system-mode emulation': have_system}
2720summary_info += {'user-mode emulation': have_user}
2721summary_info += {'block layer':       have_block}
2722summary_info += {'Install blobs':     get_option('install_blobs')}
2723summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
2724if config_host.has_key('CONFIG_MODULES')
2725  summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
2726endif
2727summary_info += {'plugin support':    config_host.has_key('CONFIG_PLUGIN')}
2728summary_info += {'fuzzing support':   config_host.has_key('CONFIG_FUZZ')}
2729if have_system
2730  summary_info += {'Audio drivers':     config_host['CONFIG_AUDIO_DRIVERS']}
2731endif
2732summary_info += {'Trace backends':    config_host['TRACE_BACKENDS']}
2733if config_host['TRACE_BACKENDS'].split().contains('simple')
2734  summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-<pid>'}
2735endif
2736summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
2737summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
2738summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
2739summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
2740summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
2741summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
2742summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
2743summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
2744summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
2745summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
2746summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
2747summary(summary_info, bool_yn: true, section: 'Configurable features')
2748
2749# Compilation information
2750summary_info = {}
2751summary_info += {'host CPU':          cpu}
2752summary_info += {'host endianness':   build_machine.endian()}
2753summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
2754summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
2755if link_language == 'cpp'
2756  summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
2757else
2758  summary_info += {'C++ compiler':      false}
2759endif
2760if targetos == 'darwin'
2761  summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
2762endif
2763if targetos == 'windows'
2764  if 'WIN_SDK' in config_host
2765    summary_info += {'Windows SDK':   config_host['WIN_SDK']}
2766  endif
2767endif
2768summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
2769                                               + ['-O' + get_option('optimization')]
2770                                               + (get_option('debug') ? ['-g'] : []))}
2771if link_language == 'cpp'
2772  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
2773                                               + ['-O' + get_option('optimization')]
2774                                               + (get_option('debug') ? ['-g'] : []))}
2775endif
2776link_args = get_option(link_language + '_link_args')
2777if link_args.length() > 0
2778  summary_info += {'LDFLAGS':         ' '.join(link_args)}
2779endif
2780summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
2781summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
2782summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
2783summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
2784summary_info += {'PIE':               get_option('b_pie')}
2785summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
2786summary_info += {'malloc trim support': has_malloc_trim}
2787summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
2788summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
2789summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
2790summary_info += {'memory allocator':  get_option('malloc')}
2791summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
2792summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
2793summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
2794summary_info += {'gcov':              get_option('b_coverage')}
2795summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
2796summary_info += {'CFI support':       get_option('cfi')}
2797if get_option('cfi')
2798  summary_info += {'CFI debug support': get_option('cfi_debug')}
2799endif
2800summary_info += {'strip binaries':    get_option('strip')}
2801summary_info += {'sparse':            sparse.found() ? sparse.full_path() : false}
2802summary_info += {'mingw32 support':   targetos == 'windows'}
2803
2804# snarf the cross-compilation information for tests
2805foreach target: target_dirs
2806  tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
2807  if fs.exists(tcg_mak)
2808    config_cross_tcg = keyval.load(tcg_mak)
2809    target = config_cross_tcg['TARGET_NAME']
2810    compiler = ''
2811    if 'DOCKER_CROSS_CC_GUEST' in config_cross_tcg
2812      summary_info += {target + ' tests': config_cross_tcg['DOCKER_CROSS_CC_GUEST'] +
2813                                          ' via ' + config_cross_tcg['DOCKER_IMAGE']}
2814    elif 'CROSS_CC_GUEST' in config_cross_tcg
2815      summary_info += {target + ' tests'
2816                                : config_cross_tcg['CROSS_CC_GUEST'] }
2817    endif
2818   endif
2819endforeach
2820
2821summary(summary_info, bool_yn: true, section: 'Compilation')
2822
2823# Targets and accelerators
2824summary_info = {}
2825if have_system
2826  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
2827  summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
2828  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
2829  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
2830  summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
2831  summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
2832  if config_host.has_key('CONFIG_XEN_BACKEND')
2833    summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
2834  endif
2835endif
2836summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
2837if config_all.has_key('CONFIG_TCG')
2838  if get_option('tcg_interpreter')
2839    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, experimental and slow)'}
2840  else
2841    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
2842  endif
2843  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
2844endif
2845summary_info += {'target list':       ' '.join(target_dirs)}
2846if have_system
2847  summary_info += {'default devices':   get_option('default_devices')}
2848  summary_info += {'out of process emulation': multiprocess_allowed}
2849endif
2850summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
2851
2852# Block layer
2853summary_info = {}
2854summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
2855summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
2856if have_block
2857  summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
2858  summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
2859  summary_info += {'VirtFS support':    have_virtfs}
2860  summary_info += {'build virtiofs daemon': have_virtiofsd}
2861  summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
2862  summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
2863  summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
2864  summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
2865  summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
2866  summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
2867  summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
2868  summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
2869  summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
2870  summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
2871  summary_info += {'FUSE exports':      fuse.found()}
2872endif
2873summary(summary_info, bool_yn: true, section: 'Block layer support')
2874
2875# Crypto
2876summary_info = {}
2877summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
2878summary_info += {'GNUTLS support':    gnutls.found()}
2879# TODO: add back version
2880summary_info += {'libgcrypt':         gcrypt.found()}
2881if gcrypt.found()
2882   summary_info += {'  XTS':             xts != 'private'}
2883endif
2884# TODO: add back version
2885summary_info += {'nettle':            nettle.found()}
2886if nettle.found()
2887   summary_info += {'  XTS':             xts != 'private'}
2888endif
2889summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
2890summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
2891summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
2892summary(summary_info, bool_yn: true, section: 'Crypto')
2893
2894# Libraries
2895summary_info = {}
2896if targetos == 'darwin'
2897  summary_info += {'Cocoa support':   cocoa.found()}
2898endif
2899# TODO: add back version
2900summary_info += {'SDL support':       sdl.found()}
2901summary_info += {'SDL image support': sdl_image.found()}
2902# TODO: add back version
2903summary_info += {'GTK support':       gtk.found()}
2904summary_info += {'pixman':            pixman.found()}
2905# TODO: add back version
2906summary_info += {'VTE support':       vte.found()}
2907# TODO: add back version
2908summary_info += {'slirp support':     slirp_opt == 'disabled' ? false : slirp_opt}
2909summary_info += {'libtasn1':          tasn1.found()}
2910summary_info += {'PAM':               pam.found()}
2911summary_info += {'iconv support':     iconv.found()}
2912summary_info += {'curses support':    curses.found()}
2913# TODO: add back version
2914summary_info += {'virgl support':     virgl.found()}
2915summary_info += {'curl support':      curl.found()}
2916summary_info += {'Multipath support': mpathpersist.found()}
2917summary_info += {'VNC support':       vnc.found()}
2918if vnc.found()
2919  summary_info += {'VNC SASL support':  sasl.found()}
2920  summary_info += {'VNC JPEG support':  jpeg.found()}
2921  summary_info += {'VNC PNG support':   png.found()}
2922endif
2923summary_info += {'brlapi support':    brlapi.found()}
2924summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
2925summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
2926summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
2927summary_info += {'Linux io_uring support': linux_io_uring.found()}
2928summary_info += {'ATTR/XATTR support': libattr.found()}
2929summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
2930summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
2931summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
2932summary_info += {'libcap-ng support': libcap_ng.found()}
2933summary_info += {'bpf support': libbpf.found()}
2934# TODO: add back protocol and server version
2935summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
2936summary_info += {'rbd support':       rbd.found()}
2937summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
2938summary_info += {'smartcard support': cacard.found()}
2939summary_info += {'U2F support':       u2f.found()}
2940summary_info += {'libusb':            libusb.found()}
2941summary_info += {'usb net redir':     usbredir.found()}
2942summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
2943summary_info += {'GBM':               config_host.has_key('CONFIG_GBM')}
2944summary_info += {'libiscsi support':  libiscsi.found()}
2945summary_info += {'libnfs support':    libnfs.found()}
2946if targetos == 'windows'
2947  if config_host.has_key('CONFIG_GUEST_AGENT')
2948    summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
2949    summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
2950  endif
2951endif
2952summary_info += {'seccomp support':   seccomp.found()}
2953summary_info += {'GlusterFS support': glusterfs.found()}
2954summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
2955summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
2956summary_info += {'lzo support':       lzo.found()}
2957summary_info += {'snappy support':    snappy.found()}
2958summary_info += {'bzip2 support':     libbzip2.found()}
2959summary_info += {'lzfse support':     liblzfse.found()}
2960summary_info += {'zstd support':      zstd.found()}
2961summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
2962summary_info += {'libxml2':           libxml2.found()}
2963summary_info += {'capstone':          capstone_opt == 'disabled' ? false : capstone_opt}
2964summary_info += {'libpmem support':   libpmem.found()}
2965summary_info += {'libdaxctl support': libdaxctl.found()}
2966summary_info += {'libudev':           libudev.found()}
2967summary_info += {'FUSE lseek':        fuse_lseek.found()}
2968summary(summary_info, bool_yn: true, section: 'Dependencies')
2969
2970if not supported_cpus.contains(cpu)
2971  message()
2972  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
2973  message()
2974  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
2975  message('The QEMU project intends to remove support for this host CPU in')
2976  message('a future release if nobody volunteers to maintain it and to')
2977  message('provide a build host for our continuous integration setup.')
2978  message('configure has succeeded and you can continue to build, but')
2979  message('if you care about QEMU on this platform you should contact')
2980  message('us upstream at qemu-devel@nongnu.org.')
2981endif
2982
2983if not supported_oses.contains(targetos)
2984  message()
2985  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
2986  message()
2987  message('Host OS ' + targetos + 'support is not currently maintained.')
2988  message('The QEMU project intends to remove support for this host OS in')
2989  message('a future release if nobody volunteers to maintain it and to')
2990  message('provide a build host for our continuous integration setup.')
2991  message('configure has succeeded and you can continue to build, but')
2992  message('if you care about QEMU on this platform you should contact')
2993  message('us upstream at qemu-devel@nongnu.org.')
2994endif
2995