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